Search in sources :

Example 16 with TransactionResultEntity

use of org.apache.nifi.web.api.entity.TransactionResultEntity in project nifi by apache.

the class TestHttpClientTransaction method testSendButDestinationFull.

@Test
public void testSendButDestinationFull() throws IOException {
    SiteToSiteRestApiClient apiClient = mock(SiteToSiteRestApiClient.class);
    final String transactionUrl = "http://www.example.com/data-transfer/input-ports/portId/transactions/transactionId";
    doNothing().when(apiClient).openConnectionForSend(eq("portId"), any(Peer.class));
    // Emulate that server returns correct checksum.
    doAnswer(new Answer() {

        @Override
        public Object answer(InvocationOnMock invocation) throws Throwable {
            HttpCommunicationsSession commSession = (HttpCommunicationsSession) invocation.getArguments()[0];
            commSession.setChecksum("3359812065");
            return null;
        }
    }).when(apiClient).finishTransferFlowFiles(any(CommunicationsSession.class));
    TransactionResultEntity resultEntity = new TransactionResultEntity();
    resultEntity.setResponseCode(ResponseCode.TRANSACTION_FINISHED_BUT_DESTINATION_FULL.getCode());
    doReturn(resultEntity).when(apiClient).commitTransferFlowFiles(eq(transactionUrl), eq(CONFIRM_TRANSACTION));
    ByteArrayOutputStream serverResponseBos = new ByteArrayOutputStream();
    ByteArrayInputStream serverResponse = new ByteArrayInputStream(serverResponseBos.toByteArray());
    ByteArrayOutputStream clientRequest = new ByteArrayOutputStream();
    HttpClientTransaction transaction = getClientTransaction(serverResponse, clientRequest, apiClient, TransferDirection.SEND, transactionUrl);
    execSendButDestinationFull(transaction);
    InputStream sentByClient = new ByteArrayInputStream(clientRequest.toByteArray());
    DataPacket packetByClient = codec.decode(sentByClient);
    assertEquals("contents on client 1", readContents(packetByClient));
    packetByClient = codec.decode(sentByClient);
    assertEquals("contents on client 2", readContents(packetByClient));
    assertEquals(-1, sentByClient.read());
    verify(apiClient).commitTransferFlowFiles(transactionUrl, CONFIRM_TRANSACTION);
}
Also used : TransactionResultEntity(org.apache.nifi.web.api.entity.TransactionResultEntity) HttpCommunicationsSession(org.apache.nifi.remote.io.http.HttpCommunicationsSession) ByteArrayInputStream(org.apache.nifi.stream.io.ByteArrayInputStream) InputStream(java.io.InputStream) SiteToSiteRestApiClient(org.apache.nifi.remote.util.SiteToSiteRestApiClient) Peer(org.apache.nifi.remote.Peer) CommunicationsSession(org.apache.nifi.remote.protocol.CommunicationsSession) HttpCommunicationsSession(org.apache.nifi.remote.io.http.HttpCommunicationsSession) ByteArrayOutputStream(org.apache.nifi.stream.io.ByteArrayOutputStream) DataPacket(org.apache.nifi.remote.protocol.DataPacket) SiteToSiteTestUtils.createDataPacket(org.apache.nifi.remote.protocol.SiteToSiteTestUtils.createDataPacket) Answer(org.mockito.stubbing.Answer) Mockito.doAnswer(org.mockito.Mockito.doAnswer) ByteArrayInputStream(org.apache.nifi.stream.io.ByteArrayInputStream) InvocationOnMock(org.mockito.invocation.InvocationOnMock) Test(org.junit.Test)

Example 17 with TransactionResultEntity

use of org.apache.nifi.web.api.entity.TransactionResultEntity in project nifi by apache.

the class DataTransferResource method commitOutputPortTransaction.

@DELETE
@Consumes(MediaType.APPLICATION_OCTET_STREAM)
@Produces(MediaType.APPLICATION_JSON)
@Path("output-ports/{portId}/transactions/{transactionId}")
@ApiOperation(value = "Commit or cancel the specified transaction", response = TransactionResultEntity.class, authorizations = { @Authorization(value = "Write - /data-transfer/output-ports/{uuid}") })
@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 commitOutputPortTransaction(@ApiParam(value = "The response code. Available values are CONFIRM_TRANSACTION(12) or CANCEL_TRANSACTION(15).", required = true) @QueryParam(RESPONSE_CODE) Integer responseCode, @ApiParam(value = "A checksum calculated at client side using CRC32 to check flow file content integrity. It must match with the value calculated at server side.", required = true) @QueryParam(CHECK_SUM) @DefaultValue(StringUtils.EMPTY) String checksum, @ApiParam(value = "The output port id.", required = true) @PathParam("portId") String portId, @ApiParam(value = "The transaction id.", required = true) @PathParam("transactionId") String transactionId, @Context HttpServletRequest req, @Context ServletContext context, InputStream inputStream) {
    // authorize access
    serviceFacade.authorizeAccess(lookup -> {
        authorizeDataTransfer(lookup, ResourceType.OutputPort, portId);
    });
    final ValidateRequestResult validationResult = validateResult(req, portId, transactionId);
    if (validationResult.errResponse != null) {
        return validationResult.errResponse;
    }
    logger.debug("commitOutputPortTransaction request: portId={}, transactionId={}", portId, transactionId);
    final int transportProtocolVersion = validationResult.transportProtocolVersion;
    final ByteArrayOutputStream out = new ByteArrayOutputStream();
    final Peer peer = constructPeer(req, inputStream, out, portId, transactionId);
    final TransactionResultEntity entity = new TransactionResultEntity();
    try {
        HttpFlowFileServerProtocol serverProtocol = initiateServerProtocol(req, peer, transportProtocolVersion);
        String inputErrMessage = null;
        if (responseCode == null) {
            inputErrMessage = "responseCode is required.";
        } else if (ResponseCode.CONFIRM_TRANSACTION.getCode() != responseCode && ResponseCode.CANCEL_TRANSACTION.getCode() != responseCode) {
            inputErrMessage = "responseCode " + responseCode + " is invalid. ";
        }
        if (inputErrMessage != null) {
            entity.setMessage(inputErrMessage);
            entity.setResponseCode(ResponseCode.ABORT.getCode());
            return Response.status(Response.Status.BAD_REQUEST).entity(entity).build();
        }
        if (ResponseCode.CANCEL_TRANSACTION.getCode() == responseCode) {
            return cancelTransaction(transactionId, entity);
        }
        int flowFileSent = serverProtocol.commitTransferTransaction(peer, checksum);
        entity.setResponseCode(ResponseCode.CONFIRM_TRANSACTION.getCode());
        entity.setFlowFileSent(flowFileSent);
    } catch (HandshakeException e) {
        return responseCreator.handshakeExceptionResponse(e);
    } catch (Exception e) {
        HttpServerCommunicationsSession commsSession = (HttpServerCommunicationsSession) peer.getCommunicationsSession();
        logger.error("Failed to process the request", e);
        if (ResponseCode.BAD_CHECKSUM.equals(commsSession.getResponseCode())) {
            entity.setResponseCode(commsSession.getResponseCode().getCode());
            entity.setMessage(e.getMessage());
            Response.ResponseBuilder builder = Response.status(Response.Status.BAD_REQUEST).entity(entity);
            return noCache(builder).build();
        }
        return responseCreator.unexpectedErrorResponse(portId, transactionId, e);
    }
    return noCache(setCommonHeaders(Response.ok(entity), transportProtocolVersion, transactionManager)).build();
}
Also used : TransactionResultEntity(org.apache.nifi.web.api.entity.TransactionResultEntity) HttpServerCommunicationsSession(org.apache.nifi.remote.io.http.HttpServerCommunicationsSession) Peer(org.apache.nifi.remote.Peer) StandardHttpFlowFileServerProtocol(org.apache.nifi.remote.protocol.http.StandardHttpFlowFileServerProtocol) HttpFlowFileServerProtocol(org.apache.nifi.remote.protocol.http.HttpFlowFileServerProtocol) ByteArrayOutputStream(org.apache.nifi.stream.io.ByteArrayOutputStream) HandshakeException(org.apache.nifi.remote.exception.HandshakeException) BadRequestException(org.apache.nifi.remote.exception.BadRequestException) HandshakeException(org.apache.nifi.remote.exception.HandshakeException) WebApplicationException(javax.ws.rs.WebApplicationException) AccessDeniedException(org.apache.nifi.authorization.AccessDeniedException) NotAuthorizedException(org.apache.nifi.remote.exception.NotAuthorizedException) IOException(java.io.IOException) UnknownHostException(java.net.UnknownHostException) RequestExpiredException(org.apache.nifi.remote.exception.RequestExpiredException) Path(javax.ws.rs.Path) DELETE(javax.ws.rs.DELETE) Consumes(javax.ws.rs.Consumes) Produces(javax.ws.rs.Produces) ApiOperation(io.swagger.annotations.ApiOperation) ApiResponses(io.swagger.annotations.ApiResponses)

Example 18 with TransactionResultEntity

use of org.apache.nifi.web.api.entity.TransactionResultEntity in project nifi by apache.

the class DataTransferResource method createPortTransaction.

@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}") })
@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);
    }
}
Also used : TransactionResultEntity(org.apache.nifi.web.api.entity.TransactionResultEntity) Peer(org.apache.nifi.remote.Peer) ByteArrayOutputStream(org.apache.nifi.stream.io.ByteArrayOutputStream) HandshakeException(org.apache.nifi.remote.exception.HandshakeException) BadRequestException(org.apache.nifi.remote.exception.BadRequestException) HandshakeException(org.apache.nifi.remote.exception.HandshakeException) WebApplicationException(javax.ws.rs.WebApplicationException) AccessDeniedException(org.apache.nifi.authorization.AccessDeniedException) NotAuthorizedException(org.apache.nifi.remote.exception.NotAuthorizedException) IOException(java.io.IOException) UnknownHostException(java.net.UnknownHostException) RequestExpiredException(org.apache.nifi.remote.exception.RequestExpiredException) Path(javax.ws.rs.Path) POST(javax.ws.rs.POST) Produces(javax.ws.rs.Produces) ApiOperation(io.swagger.annotations.ApiOperation) ApiResponses(io.swagger.annotations.ApiResponses)

Example 19 with TransactionResultEntity

use of org.apache.nifi.web.api.entity.TransactionResultEntity in project nifi by apache.

the class DataTransferResource method commitInputPortTransaction.

@DELETE
@Consumes(MediaType.APPLICATION_OCTET_STREAM)
@Produces(MediaType.APPLICATION_JSON)
@Path("input-ports/{portId}/transactions/{transactionId}")
@ApiOperation(value = "Commit or cancel the specified transaction", response = TransactionResultEntity.class, authorizations = { @Authorization(value = "Write - /data-transfer/input-ports/{uuid}") })
@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 commitInputPortTransaction(@ApiParam(value = "The response code. Available values are BAD_CHECKSUM(19), CONFIRM_TRANSACTION(12) or CANCEL_TRANSACTION(15).", required = true) @QueryParam(RESPONSE_CODE) Integer responseCode, @ApiParam(value = "The input port id.", required = true) @PathParam("portId") String portId, @ApiParam(value = "The transaction id.", required = true) @PathParam("transactionId") String transactionId, @Context HttpServletRequest req, @Context ServletContext context, InputStream inputStream) {
    // authorize access
    serviceFacade.authorizeAccess(lookup -> {
        authorizeDataTransfer(lookup, ResourceType.InputPort, portId);
    });
    final ValidateRequestResult validationResult = validateResult(req, portId, transactionId);
    if (validationResult.errResponse != null) {
        return validationResult.errResponse;
    }
    logger.debug("commitInputPortTransaction request: portId={}, transactionId={}, responseCode={}", portId, transactionId, responseCode);
    final int transportProtocolVersion = validationResult.transportProtocolVersion;
    final ByteArrayOutputStream out = new ByteArrayOutputStream();
    final Peer peer = constructPeer(req, inputStream, out, portId, transactionId);
    final TransactionResultEntity entity = new TransactionResultEntity();
    try {
        HttpFlowFileServerProtocol serverProtocol = initiateServerProtocol(req, peer, transportProtocolVersion);
        HttpServerCommunicationsSession commsSession = (HttpServerCommunicationsSession) peer.getCommunicationsSession();
        // Pass the response code sent from the client.
        String inputErrMessage = null;
        if (responseCode == null) {
            inputErrMessage = "responseCode is required.";
        } else if (ResponseCode.BAD_CHECKSUM.getCode() != responseCode && ResponseCode.CONFIRM_TRANSACTION.getCode() != responseCode && ResponseCode.CANCEL_TRANSACTION.getCode() != responseCode) {
            inputErrMessage = "responseCode " + responseCode + " is invalid. ";
        }
        if (inputErrMessage != null) {
            entity.setMessage(inputErrMessage);
            entity.setResponseCode(ResponseCode.ABORT.getCode());
            return Response.status(Response.Status.BAD_REQUEST).entity(entity).build();
        }
        if (ResponseCode.CANCEL_TRANSACTION.getCode() == responseCode) {
            return cancelTransaction(transactionId, entity);
        }
        commsSession.setResponseCode(ResponseCode.fromCode(responseCode));
        try {
            int flowFileSent = serverProtocol.commitReceiveTransaction(peer);
            entity.setResponseCode(commsSession.getResponseCode().getCode());
            entity.setFlowFileSent(flowFileSent);
        } catch (IOException e) {
            if (ResponseCode.BAD_CHECKSUM.getCode() == responseCode && e.getMessage().contains("Received a BadChecksum response")) {
                // AbstractFlowFileServerProtocol throws IOException after it canceled transaction.
                // This is a known behavior and if we return 500 with this exception,
                // it's not clear if there is an issue at server side, or cancel operation has been accomplished.
                // Above conditions can guarantee this is the latter case, we return 200 OK here.
                entity.setResponseCode(ResponseCode.CANCEL_TRANSACTION.getCode());
                return noCache(Response.ok(entity)).build();
            } else {
                return responseCreator.unexpectedErrorResponse(portId, transactionId, e);
            }
        }
    } catch (HandshakeException e) {
        return responseCreator.handshakeExceptionResponse(e);
    } catch (Exception e) {
        return responseCreator.unexpectedErrorResponse(portId, transactionId, e);
    }
    return noCache(setCommonHeaders(Response.ok(entity), transportProtocolVersion, transactionManager)).build();
}
Also used : TransactionResultEntity(org.apache.nifi.web.api.entity.TransactionResultEntity) HttpServerCommunicationsSession(org.apache.nifi.remote.io.http.HttpServerCommunicationsSession) Peer(org.apache.nifi.remote.Peer) StandardHttpFlowFileServerProtocol(org.apache.nifi.remote.protocol.http.StandardHttpFlowFileServerProtocol) HttpFlowFileServerProtocol(org.apache.nifi.remote.protocol.http.HttpFlowFileServerProtocol) ByteArrayOutputStream(org.apache.nifi.stream.io.ByteArrayOutputStream) IOException(java.io.IOException) HandshakeException(org.apache.nifi.remote.exception.HandshakeException) BadRequestException(org.apache.nifi.remote.exception.BadRequestException) HandshakeException(org.apache.nifi.remote.exception.HandshakeException) WebApplicationException(javax.ws.rs.WebApplicationException) AccessDeniedException(org.apache.nifi.authorization.AccessDeniedException) NotAuthorizedException(org.apache.nifi.remote.exception.NotAuthorizedException) IOException(java.io.IOException) UnknownHostException(java.net.UnknownHostException) RequestExpiredException(org.apache.nifi.remote.exception.RequestExpiredException) Path(javax.ws.rs.Path) DELETE(javax.ws.rs.DELETE) Consumes(javax.ws.rs.Consumes) Produces(javax.ws.rs.Produces) ApiOperation(io.swagger.annotations.ApiOperation) ApiResponses(io.swagger.annotations.ApiResponses)

Example 20 with TransactionResultEntity

use of org.apache.nifi.web.api.entity.TransactionResultEntity in project nifi by apache.

the class DataTransferResource method extendPortTransactionTTL.

public Response extendPortTransactionTTL(String portType, String portId, String transactionId, HttpServletRequest req, HttpServletResponse res, ServletContext context, UriInfo uriInfo, InputStream inputStream) {
    final ValidateRequestResult validationResult = validateResult(req, portId, transactionId);
    if (validationResult.errResponse != null) {
        return validationResult.errResponse;
    }
    if (!PORT_TYPE_INPUT.equals(portType) && !PORT_TYPE_OUTPUT.equals(portType)) {
        return responseCreator.wrongPortTypeResponse(portType, portId);
    }
    logger.debug("extendOutputPortTransactionTTL request: portType={}, portId={}, transactionId={}", portType, portId, transactionId);
    final int transportProtocolVersion = validationResult.transportProtocolVersion;
    final ByteArrayOutputStream out = new ByteArrayOutputStream();
    final Peer peer = constructPeer(req, inputStream, out, portId, transactionId);
    try {
        // Do handshake
        initiateServerProtocol(req, peer, transportProtocolVersion);
        transactionManager.extendTransaction(transactionId);
        final TransactionResultEntity entity = new TransactionResultEntity();
        entity.setResponseCode(ResponseCode.CONTINUE_TRANSACTION.getCode());
        entity.setMessage("Extended TTL.");
        return noCache(setCommonHeaders(Response.ok(entity), transportProtocolVersion, transactionManager)).build();
    } catch (HandshakeException e) {
        return responseCreator.handshakeExceptionResponse(e);
    } catch (Exception e) {
        return responseCreator.unexpectedErrorResponse(portId, transactionId, e);
    }
}
Also used : TransactionResultEntity(org.apache.nifi.web.api.entity.TransactionResultEntity) Peer(org.apache.nifi.remote.Peer) ByteArrayOutputStream(org.apache.nifi.stream.io.ByteArrayOutputStream) HandshakeException(org.apache.nifi.remote.exception.HandshakeException) BadRequestException(org.apache.nifi.remote.exception.BadRequestException) HandshakeException(org.apache.nifi.remote.exception.HandshakeException) WebApplicationException(javax.ws.rs.WebApplicationException) AccessDeniedException(org.apache.nifi.authorization.AccessDeniedException) NotAuthorizedException(org.apache.nifi.remote.exception.NotAuthorizedException) IOException(java.io.IOException) UnknownHostException(java.net.UnknownHostException) RequestExpiredException(org.apache.nifi.remote.exception.RequestExpiredException)

Aggregations

TransactionResultEntity (org.apache.nifi.web.api.entity.TransactionResultEntity)24 Test (org.junit.Test)16 InputStream (java.io.InputStream)12 ByteArrayOutputStream (org.apache.nifi.stream.io.ByteArrayOutputStream)12 Peer (org.apache.nifi.remote.Peer)11 HttpServletRequest (javax.servlet.http.HttpServletRequest)9 Response (javax.ws.rs.core.Response)9 HandshakeException (org.apache.nifi.remote.exception.HandshakeException)9 ServletContext (javax.servlet.ServletContext)8 HttpServletResponse (javax.servlet.http.HttpServletResponse)8 ByteArrayInputStream (org.apache.nifi.stream.io.ByteArrayInputStream)8 SiteToSiteRestApiClient (org.apache.nifi.remote.util.SiteToSiteRestApiClient)7 HttpCommunicationsSession (org.apache.nifi.remote.io.http.HttpCommunicationsSession)6 HttpFlowFileServerProtocol (org.apache.nifi.remote.protocol.http.HttpFlowFileServerProtocol)6 IOException (java.io.IOException)5 UriInfo (javax.ws.rs.core.UriInfo)5 UnknownHostException (java.net.UnknownHostException)4 WebApplicationException (javax.ws.rs.WebApplicationException)4 AccessDeniedException (org.apache.nifi.authorization.AccessDeniedException)4 HttpRemoteSiteListener (org.apache.nifi.remote.HttpRemoteSiteListener)4