@Override public NextAction processRequest(Packet request) { try { LOGGER.entering(); assert request.getMessage() != null : "Unexpected [null] message in the server-side Tube.processRequest()"; String clientUID = getClientUID(request); if (isMakeConnectionRequest(request)) { return handleMakeConnectionRequest(request, clientUID); } if (clientUID == null) { // don't bother - this is not a WS-MC enabled request return super.processRequest(request); } else { // TODO replace with proper code that replaces only address // removing replyTo header and faultTo header to prevent addressing server tube from // treating this request as non-anonymous request.getMessage().getHeaders().remove(configuration.getAddressingVersion().replyToTag); request.getMessage().getHeaders().remove(configuration.getAddressingVersion().faultToTag); } Packet requestCopy = request.copy(true); fiberExecutor.start( request, new AppRequestProcessingCallback(responseStorage, clientUID, configuration)); return super.doReturnWith(createEmptyResponse(requestCopy)); } finally { LOGGER.exiting(); } }
@Override public AbstractTubeImpl copy(TubeCloner cloner) { LOGGER.entering(); try { return new McServerTube(this, cloner); } finally { LOGGER.exiting(); } }
@Override public NextAction processException(Throwable t) { try { LOGGER.entering(); return super.processException(t); } finally { LOGGER.exiting(); } }
public void putToDeliveryQueue(ApplicationMessage message) throws RxRuntimeException { assert sequenceManager != null; if (LOGGER.isLoggable(Level.FINER)) { LOGGER.finer( String.format( "Putting a message with number [ %d ] to the delivery queue of a sequence [ %s ]", message.getMessageNumber(), message.getSequenceId())); } sequenceManager.getSequence(message.getSequenceId()).getDeliveryQueue().put(message); }
@Override public NextAction processResponse(Packet response) { try { LOGGER.entering(); // with WS-MC enabled messages, this method gets never invoked return super.processResponse(response); } finally { LOGGER.exiting(); } }
class ClientDestinationDeliveryCallback implements Postman.Callback { private static final Logger LOGGER = Logger.getLogger(ClientDestinationDeliveryCallback.class); private final RuntimeContext rc; public ClientDestinationDeliveryCallback(RuntimeContext rc) { this.rc = rc; } public void deliver(ApplicationMessage message) { if (message instanceof JaxwsApplicationMessage) { deliver(JaxwsApplicationMessage.class.cast(message)); } else { throw LOGGER.logSevereException( new RxRuntimeException( LocalizationMessages.WSRM_1141_UNEXPECTED_MESSAGE_CLASS( message.getClass().getName(), JaxwsApplicationMessage.class.getName()))); } } private void deliver(JaxwsApplicationMessage message) { rc.suspendedFiberStorage.resumeFiber(message.getCorrelationId(), message.getPacket()); rc.destinationMessageHandler.acknowledgeApplicationLayerDelivery(message); } }
public List<Device> getDevices() { try { Builder obj = service .path(pathString) .path(labBookPath + "/device") .accept(MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON); IndexBean indexBean = FacesContext.getCurrentInstance() .getApplication() .evaluateExpressionGet( FacesContext.getCurrentInstance(), "#{indexBean}", IndexBean.class); Object username = indexBean.getLoginUserName(); obj.header("username", username); DeviceListServiceBean result = obj.get(new GenericType<DeviceListServiceBean>() {}); List<Device> itemList = result.getDeviceList(); for (Item it : itemList) { string = it.getName(); System.out.println(string); } return itemList; } catch (Exception e) { Logger.getLogger(this.getClass()) .log(Level.SEVERE, "LabBookToolClient.getDevices() exception occured", e); } return null; }
public void deliver(ApplicationMessage message) { if (message instanceof JaxwsApplicationMessage) { deliver(JaxwsApplicationMessage.class.cast(message)); } else { throw LOGGER.logSevereException( new RxRuntimeException( LocalizationMessages.WSRM_1141_UNEXPECTED_MESSAGE_CLASS( message.getClass().getName(), JaxwsApplicationMessage.class.getName()))); } }
public void onCompletion(Packet response) { LOGGER.finer(LocalizationMessages.WSMC_0105_STORING_RESPONSE(clientUID)); if (response.getMessage() != null) { final HeaderList headers = response.getMessage().getHeaders(); headers.remove(configuration.getAddressingVersion().toTag); headers.add( Headers.create( configuration.getAddressingVersion().toTag, configuration.getMcVersion().getWsmcAnonymousAddress(clientUID))); } responseStorage.store(response, clientUID); }
private String getClientUID(Packet request) { Header replyToHeader = request .getMessage() .getHeaders() .get(configuration.getAddressingVersion().replyToTag, false); if (replyToHeader != null) { try { String replyToAddress = replyToHeader.readAsEPR(configuration.getAddressingVersion()).getAddress(); return configuration.getMcVersion().getClientId(replyToAddress); } catch (XMLStreamException ex) { throw LOGGER.logSevereException( new RxRuntimeException( LocalizationMessages.WSMC_0103_ERROR_RETRIEVING_WSA_REPLYTO_CONTENT(), ex)); } } return null; }
public List<Laptop> getLaptops() { try { Builder obj = service .path(pathString) .path(labBookPath + "/laptop") .accept(MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON); LaptopListServiceBean result = obj.get(new GenericType<LaptopListServiceBean>() {}); List<Laptop> laptopList = result.getLaptopList(); for (Item it : laptopList) { string = it.getName(); System.out.println(string); } return laptopList; } catch (Exception e) { Logger.getLogger(this.getClass()) .log(Level.SEVERE, "LabBookToolClient.getDevices() exception occured", e); } return new ArrayList<Laptop>(); }
private static final class AppRequestProcessingCallback implements Fiber.CompletionCallback { private static final Logger LOGGER = Logger.getLogger(AppRequestProcessingCallback.class); private final ResponseStorage responseStorage; private final String clientUID; private final McConfiguration configuration; public AppRequestProcessingCallback( @NotNull ResponseStorage responseStorage, @NotNull String clientUID, @NotNull McConfiguration configuration) { this.responseStorage = responseStorage; this.clientUID = clientUID; this.configuration = configuration; } public void onCompletion(Packet response) { LOGGER.finer(LocalizationMessages.WSMC_0105_STORING_RESPONSE(clientUID)); if (response.getMessage() != null) { final HeaderList headers = response.getMessage().getHeaders(); headers.remove(configuration.getAddressingVersion().toTag); headers.add( Headers.create( configuration.getAddressingVersion().toTag, configuration.getMcVersion().getWsmcAnonymousAddress(clientUID))); } responseStorage.store(response, clientUID); } public void onCompletion(Throwable error) { LOGGER.severe( LocalizationMessages.WSMC_0106_EXCEPTION_IN_REQUEST_PROCESSING(clientUID), error); } }
/** * Handles outgoing application messages. This class encapsulates RM Source logic that is * independent on of the actual delivery mechanism or framework (such as JAX-WS fibers). * * @author Marek Potociar <marek.potociar at sun.com> */ class SourceMessageHandler implements MessageHandler { private static final Logger LOGGER = Logger.getLogger(SourceMessageHandler.class); private volatile SequenceManager sequenceManager; SourceMessageHandler(@Nullable SequenceManager sequenceManager) { this.sequenceManager = sequenceManager; } void setSequenceManager(SequenceManager sequenceManager) { this.sequenceManager = sequenceManager; } /** * Registers outgoing message with the provided outbound sequence and sets sequenceId and * messageNumber properties on the outgoing message. * * <p>Once the message is registered and properties are set, the message is placed into a delivery * queue and delivery callback is invoked. * * @throws UnknownSequenceException if no such sequence exits for a given sequence identifier */ public void registerMessage( @NotNull ApplicationMessage outMessage, @NotNull String outboundSequenceId) throws DuplicateMessageRegistrationException, UnknownSequenceException { assert sequenceManager != null; assert outMessage != null; assert outboundSequenceId != null; final Sequence outboundSequence = sequenceManager.getSequence(outboundSequenceId); outboundSequence.registerMessage( outMessage, true); // TODO it may not be needed to store message if AtMostOnce delivery } /** * Attaches RM acknowledgement information such as inbound sequence acknowledgements (if there is * an inbound sequence bound to the specified outbound sequence) or outbound sequence * acknowledgement requested flag to the outgoing message. * * @throws UnknownSequenceException if no such sequence exits for a given sequence identifier */ public void attachAcknowledgementInfo(@NotNull ApplicationMessage outMessage) throws UnknownSequenceException { assert sequenceManager != null; assert outMessage != null; assert outMessage.getSequenceId() != null; // inbound sequence acknowledgements outMessage.setAcknowledgementData(getAcknowledgementData(outMessage.getSequenceId())); } /** * Retrieves acknowledgement information for a given outbound (and inbound) sequence * * @param outboundSequenceId outbound sequence identifier * @return acknowledgement information for a given outbound sequence * @throws UnknownSequenceException if no such sequence exits for a given sequence identifier */ public AcknowledgementData getAcknowledgementData(String outboundSequenceId) throws UnknownSequenceException { assert sequenceManager != null; AcknowledgementData.Builder ackDataBuilder = AcknowledgementData.getBuilder(); Sequence inboundSequence = sequenceManager.getBoundSequence(outboundSequenceId); if (inboundSequence != null) { /** * If inbound sequence exists, we are not checking if inboundSequence.isAckRequested() is * true. Instead, we are allways attaching inbound sequence acknowledegements (even if not * requested by the other side) This is to avoid potential locks in InOrder * delivery/redelivery scenarios. * * <p>For example, following could happen on the client side with InOrder enabled if we * strictly checked for inboundSequence.isAckRequested() to be true: * * <p>0. response to a previous client request arrives, endpoint is waiting for an * acknowledgement 1. client request is put to delivery queue 2. acknowledgements are attached * to the client request and ackRequested flag is cleared on inbound sequence 3. client * request gets lost. 4. client request is scheduled for a resend 5. client request is put to * delivery queue 6. this time, ackRequested flag is clear, so we will not append any * acknowledgements 7. client request is processed on the endpoint and response is put to the * endpoint's source delivery queue 8. since there was no acknowledgement of the previous * response, the new response is blocekd in the delivery queue forever * * <p>After step 8., communication between client and endpoint might freeze in a deadlock * unless another means of communicating the sequence acknowledgements from client to the * endpoint are established. */ ackDataBuilder.acknowledgements( inboundSequence.getId(), inboundSequence.getAcknowledgedMessageNumbers(), inboundSequence.isClosed()); inboundSequence.clearAckRequestedFlag(); } // outbound sequence ack requested flag final Sequence outboundSequence = sequenceManager.getSequence(outboundSequenceId); if (outboundSequence.hasUnacknowledgedMessages()) { ackDataBuilder.ackReqestedSequenceId(outboundSequenceId); outboundSequence.updateLastAcknowledgementRequestTime(); } final AcknowledgementData acknowledgementData = ackDataBuilder.build(); return acknowledgementData; } public void putToDeliveryQueue(ApplicationMessage message) throws RxRuntimeException { assert sequenceManager != null; if (LOGGER.isLoggable(Level.FINER)) { LOGGER.finer( String.format( "Putting a message with number [ %d ] to the delivery queue of a sequence [ %s ]", message.getMessageNumber(), message.getSequenceId())); } sequenceManager.getSequence(message.getSequenceId()).getDeliveryQueue().put(message); } }
/** @author Marek Potociar <marek.potociar at sun.com> */ public class McServerTube extends AbstractFilterTubeImpl { private static final class ResponseStorage { final Map<String, Queue<Packet>> storage = new HashMap<String, Queue<Packet>>(); final ReentrantReadWriteLock storageLock = new ReentrantReadWriteLock(); void store(@NotNull Packet response, @NotNull String clientUID) { if (!getClientQueue(clientUID).offer(response)) { LOGGER.severe(LocalizationMessages.WSMC_0104_ERROR_STORING_RESPONSE(clientUID)); } } private Packet getPendingResponsePacket(@NotNull String clientUID) { try { storageLock.readLock().lock(); final Queue<Packet> clientQueue = storage.get(clientUID); return (clientQueue == null) ? null : clientQueue.poll(); } finally { storageLock.readLock().unlock(); } } private boolean hasPendingResponse(@NotNull String clientUID) { try { storageLock.readLock().lock(); final Queue<Packet> clientQueue = storage.get(clientUID); return clientQueue != null && !clientQueue.isEmpty(); } finally { storageLock.readLock().unlock(); } } private Queue<Packet> getClientQueue(@NotNull String clientUID) { try { storageLock.readLock().lock(); Queue<Packet> clientQueue = storage.get(clientUID); if (clientQueue == null) { storageLock.readLock().unlock(); try { storageLock.writeLock().lock(); clientQueue = storage.get(clientUID); if (clientQueue == null) { // recheck clientQueue = new ConcurrentLinkedQueue<Packet>(); storage.put(clientUID, clientQueue); } storageLock.readLock().lock(); } finally { storageLock.writeLock().unlock(); } } return clientQueue; } finally { storageLock.readLock().unlock(); } } } private static final class AppRequestProcessingCallback implements Fiber.CompletionCallback { private static final Logger LOGGER = Logger.getLogger(AppRequestProcessingCallback.class); private final ResponseStorage responseStorage; private final String clientUID; private final McConfiguration configuration; public AppRequestProcessingCallback( @NotNull ResponseStorage responseStorage, @NotNull String clientUID, @NotNull McConfiguration configuration) { this.responseStorage = responseStorage; this.clientUID = clientUID; this.configuration = configuration; } public void onCompletion(Packet response) { LOGGER.finer(LocalizationMessages.WSMC_0105_STORING_RESPONSE(clientUID)); if (response.getMessage() != null) { final HeaderList headers = response.getMessage().getHeaders(); headers.remove(configuration.getAddressingVersion().toTag); headers.add( Headers.create( configuration.getAddressingVersion().toTag, configuration.getMcVersion().getWsmcAnonymousAddress(clientUID))); } responseStorage.store(response, clientUID); } public void onCompletion(Throwable error) { LOGGER.severe( LocalizationMessages.WSMC_0106_EXCEPTION_IN_REQUEST_PROCESSING(clientUID), error); } } // private static final Logger LOGGER = Logger.getLogger(McServerTube.class); // private final McConfiguration configuration; private final FiberExecutor fiberExecutor; private final ResponseStorage responseStorage; McServerTube(McConfiguration configuration, Tube tubelineHead) { super(tubelineHead); this.configuration = configuration; this.fiberExecutor = new FiberExecutor("McServerTubeCommunicator", tubelineHead); this.responseStorage = new ResponseStorage(); } McServerTube(McServerTube original, TubeCloner cloner) { super(original, cloner); this.configuration = original.configuration; this.fiberExecutor = original.fiberExecutor; this.responseStorage = original.responseStorage; } @Override public AbstractTubeImpl copy(TubeCloner cloner) { LOGGER.entering(); try { return new McServerTube(this, cloner); } finally { LOGGER.exiting(); } } @Override public NextAction processRequest(Packet request) { try { LOGGER.entering(); assert request.getMessage() != null : "Unexpected [null] message in the server-side Tube.processRequest()"; String clientUID = getClientUID(request); if (isMakeConnectionRequest(request)) { return handleMakeConnectionRequest(request, clientUID); } if (clientUID == null) { // don't bother - this is not a WS-MC enabled request return super.processRequest(request); } else { // TODO replace with proper code that replaces only address // removing replyTo header and faultTo header to prevent addressing server tube from // treating this request as non-anonymous request.getMessage().getHeaders().remove(configuration.getAddressingVersion().replyToTag); request.getMessage().getHeaders().remove(configuration.getAddressingVersion().faultToTag); } Packet requestCopy = request.copy(true); fiberExecutor.start( request, new AppRequestProcessingCallback(responseStorage, clientUID, configuration)); return super.doReturnWith(createEmptyResponse(requestCopy)); } finally { LOGGER.exiting(); } } @Override public NextAction processResponse(Packet response) { try { LOGGER.entering(); // with WS-MC enabled messages, this method gets never invoked return super.processResponse(response); } finally { LOGGER.exiting(); } } private NextAction handleMakeConnectionRequest(Packet request, String clientUID) { try { LOGGER.entering(); String selectionUID; try { MakeConnectionElement mcElement = request .getMessage() .readPayloadAsJAXB( configuration .getMcVersion() .getUnmarshaller(configuration.getAddressingVersion())); selectionUID = configuration.getMcVersion().getClientId(mcElement.getAddress().getValue()); } catch (JAXBException ex) { throw LOGGER.logSevereException( new RxRuntimeException( LocalizationMessages.WSMC_0107_ERROR_UNMARSHALLING_PROTOCOL_MESSAGE(), ex)); } if (selectionUID == null) { // TODO return a MissingSelection SOAP fault throw LOGGER.logSevereException( new RxRuntimeException(LocalizationMessages.WSMC_0108_NULL_SELECTION_ADDRESS())); } if (!selectionUID.equals(clientUID)) { // TODO return a SOAP fault? throw LOGGER.logSevereException( new RxRuntimeException( LocalizationMessages.WSMC_0109_SELECTION_ADDRESS_NOT_MATCHING_WSA_REPLYTO())); } Packet response = null; if (selectionUID != null && responseStorage.hasPendingResponse(selectionUID)) { LOGGER.finer( LocalizationMessages.WSMC_0110_PENDING_MESSAGE_FOUND_FOR_SELECTION_UUID(selectionUID)); response = responseStorage.getPendingResponsePacket(selectionUID); } if (response == null) { LOGGER.finer( LocalizationMessages.WSMC_0111_NO_PENDING_MESSAGE_FOUND_FOR_SELECTION_UUID( selectionUID)); response = createEmptyResponse(request); } else { Message message = response.getMessage(); if (message != null) { HeaderList headers = message.getHeaders(); headers.add( Headers.create( configuration.getMcVersion().getJaxbContext(configuration.getAddressingVersion()), new MessagePendingElement( Boolean.valueOf( selectionUID != null && responseStorage.hasPendingResponse(selectionUID))))); } } return super.doReturnWith(response); } finally { LOGGER.exiting(); } } @Override public NextAction processException(Throwable t) { try { LOGGER.entering(); return super.processException(t); } finally { LOGGER.exiting(); } } @Override public void preDestroy() { super.preDestroy(); } private String getClientUID(Packet request) { Header replyToHeader = request .getMessage() .getHeaders() .get(configuration.getAddressingVersion().replyToTag, false); if (replyToHeader != null) { try { String replyToAddress = replyToHeader.readAsEPR(configuration.getAddressingVersion()).getAddress(); return configuration.getMcVersion().getClientId(replyToAddress); } catch (XMLStreamException ex) { throw LOGGER.logSevereException( new RxRuntimeException( LocalizationMessages.WSMC_0103_ERROR_RETRIEVING_WSA_REPLYTO_CONTENT(), ex)); } } return null; } private boolean isMakeConnectionRequest(final Packet request) { return configuration .getMcVersion() .wsmcAction .equals( request .getMessage() .getHeaders() .getAction(configuration.getAddressingVersion(), configuration.getSoapVersion())); } private Packet createEmptyResponse(Packet request) { return request.createServerResponse(null, null, null, ""); } }
private NextAction handleMakeConnectionRequest(Packet request, String clientUID) { try { LOGGER.entering(); String selectionUID; try { MakeConnectionElement mcElement = request .getMessage() .readPayloadAsJAXB( configuration .getMcVersion() .getUnmarshaller(configuration.getAddressingVersion())); selectionUID = configuration.getMcVersion().getClientId(mcElement.getAddress().getValue()); } catch (JAXBException ex) { throw LOGGER.logSevereException( new RxRuntimeException( LocalizationMessages.WSMC_0107_ERROR_UNMARSHALLING_PROTOCOL_MESSAGE(), ex)); } if (selectionUID == null) { // TODO return a MissingSelection SOAP fault throw LOGGER.logSevereException( new RxRuntimeException(LocalizationMessages.WSMC_0108_NULL_SELECTION_ADDRESS())); } if (!selectionUID.equals(clientUID)) { // TODO return a SOAP fault? throw LOGGER.logSevereException( new RxRuntimeException( LocalizationMessages.WSMC_0109_SELECTION_ADDRESS_NOT_MATCHING_WSA_REPLYTO())); } Packet response = null; if (selectionUID != null && responseStorage.hasPendingResponse(selectionUID)) { LOGGER.finer( LocalizationMessages.WSMC_0110_PENDING_MESSAGE_FOUND_FOR_SELECTION_UUID(selectionUID)); response = responseStorage.getPendingResponsePacket(selectionUID); } if (response == null) { LOGGER.finer( LocalizationMessages.WSMC_0111_NO_PENDING_MESSAGE_FOUND_FOR_SELECTION_UUID( selectionUID)); response = createEmptyResponse(request); } else { Message message = response.getMessage(); if (message != null) { HeaderList headers = message.getHeaders(); headers.add( Headers.create( configuration.getMcVersion().getJaxbContext(configuration.getAddressingVersion()), new MessagePendingElement( Boolean.valueOf( selectionUID != null && responseStorage.hasPendingResponse(selectionUID))))); } } return super.doReturnWith(response); } finally { LOGGER.exiting(); } }
public void onCompletion(Throwable error) { LOGGER.severe( LocalizationMessages.WSMC_0106_EXCEPTION_IN_REQUEST_PROCESSING(clientUID), error); }