class DataTransferResource extends ApplicationResource {

    @POST
    @Produces(MediaType.APPLICATION_JSON)
    @Path("{portType}/{portId}/transactions")
    @ApiOperation(
            value = "Create a transaction to the specified output port or input port",
            response = TransactionResultEntity.class,
            authorizations = {
                    @Authorization(value = "Write - /data-transfer/{component-type}/{uuid}", type = "")
            }
    )
    @ApiResponses(
            value = {
                    @ApiResponse(code = 400, message = "NiFi was unable to complete the request because it was invalid. The request should not be retried without modification."),
                    @ApiResponse(code = 401, message = "Client could not be authenticated."),
                    @ApiResponse(code = 403, message = "Client is not authorized to make this request."),
                    @ApiResponse(code = 404, message = "The specified resource could not be found."),
                    @ApiResponse(code = 409, message = "The request was valid but NiFi was not in the appropriate state to process it. Retrying the same request later may be successful."),
                    @ApiResponse(code = 503, message = "NiFi instance is not ready for serving request, or temporarily overloaded. Retrying the same request later may be successful"),
            }
    )
    public Response createPortTransaction(
            @ApiParam(
                    value = "The port type.",
                    required = true,
                    allowableValues = "input-ports, output-ports"
            )
            @PathParam("portType") String portType,
            @PathParam("portId") String portId,
            @Context HttpServletRequest req,
            @Context ServletContext context,
            @Context UriInfo uriInfo,
            InputStream inputStream) {


        if (!PORT_TYPE_INPUT.equals(portType) && !PORT_TYPE_OUTPUT.equals(portType)) {
            return responseCreator.wrongPortTypeResponse(portType, portId);
        }

        // authorize access
        serviceFacade.authorizeAccess(lookup -> {
            authorizeDataTransfer(lookup, PORT_TYPE_INPUT.equals(portType) ? ResourceType.InputPort : ResourceType.OutputPort, portId);
        });

        final ValidateRequestResult validationResult = validateResult(req, portId);
        if (validationResult.errResponse != null) {
            return validationResult.errResponse;
        }

        logger.debug("createPortTransaction request: clientId={}, portType={}, portId={}", portType, portId);

        final ByteArrayOutputStream out = new ByteArrayOutputStream();
        final String transactionId = transactionManager.createTransaction();
        final Peer peer = constructPeer(req, inputStream, out, portId, transactionId);
        final int transportProtocolVersion = validationResult.transportProtocolVersion;

        try {
            // Execute handshake.
            initiateServerProtocol(req, peer, transportProtocolVersion);

            TransactionResultEntity entity = new TransactionResultEntity();
            entity.setResponseCode(ResponseCode.PROPERTIES_OK.getCode());
            entity.setMessage("Handshake properties are valid, and port is running. A transaction is created:" + transactionId);

            return responseCreator.locationResponse(uriInfo, portType, portId, transactionId, entity, transportProtocolVersion, transactionManager);

        } catch (HandshakeException e) {
            transactionManager.cancelTransaction(transactionId);
            return responseCreator.handshakeExceptionResponse(e);

        } catch (Exception e) {
            transactionManager.cancelTransaction(transactionId);
            return responseCreator.unexpectedErrorResponse(portId, e);
        }
    }

    public  DataTransferResource(final NiFiProperties nifiProperties);

}