2012-12-13 24 views
5

Tôi đang cố gắng phát triển một điều phối từ xa với CXF bằng cách sử dụng javax.xml.ws.Provider như được giải thích ở đây: http://cxf.apache.org/docs/jax-ws-dispatch-api.html. Tôi đã một khách hàng CXF cấu hình với WSAddressing, SOAP12_HTTP_BINDING và với các cấu hình WSS4J sau: WSS4JCông văn CXF WS không thành công khi trả lại cho khách hàng

khách hàng trong đánh chặn:

inProps.put("action",     "Timestamp Signature Encrypt");  
inProps.put("passwordType",   "PasswordText"); 
    ... 

Khách hàng WSS4J OUT đánh chặn:

protected static final String WSU_NS = 
    "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd";           
protected static final String SOAP12_NS = "http://www.w3.org/2003/05/soap-envelope"; 
protected static final String SOAP11_NS = "http://schemas.xmlsoap.org/soap/envelope"; 
protected static final String WSA_NS = "http://www.w3.org/2005/08/addressing"; 
protected static final String WSSE_NS="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"; 

String userForPswCallback = ... 
Map<String, Object> props = new HashMap<String, Object>(); 
props.put("action",     "UsernameToken Timestamp Signature Encrypt"); 
props.put("passwordType",   "PasswordText"); 
... 
props.put("encryptionParts",  "{Content}{"+SOAP12_NS+"}Body;{Element}{"+WSSE_NS+"}UsernameToken"); 
props.put("signatureKeyIdentifier", "DirectReference"); 
props.put("signatureParts",   "{Element}{"+SOAP12_NS+"}Body;" + 
       "{Element}{"+WSSE_NS+"}UsernameToken;" + 
       "{Element}{"+WSA_NS+"}Action;" + 
       "{Element}{"+WSA_NS+"}MessageID;" + 
       "{Element}{"+WSA_NS+"}To;" + 
       "{Element}{"+WSA_NS+"}ReplyTo"); 

Tại phía dispatcher tôi xuất bản dịch vụ điều phối sau đây:

@WebServiceProvider(targetNamespace = JettyConstants.PersistenceNameSpace, 
        serviceName=JettyConstants.PersistenceService, 
        portName=JettyConstants.PersistencePort) 
@ServiceMode (Service.Mode.MESSAGE) 
public class PersistenceProvider implements Provider<Source> { 
    private static final Logger log = Logger.getLogger(PersistenceProvider.class); 

    private TransformerFactory transformerFactory; 

    public PersistenceProvider() { 
     // Complete 
    } 

    private static final DocumentBuilderFactory BUILDER_FACTORY = DocumentBuilderFactory.newInstance(); 
    static { 
      BUILDER_FACTORY.setNamespaceAware(true); 
    } 

    public Source invoke(Source request) { 
     try { 
      DOMSource sourceInvoke = null; 

      //get userName and userPassword from the interceptor chain (added in a custom interceptor) 
      String userName = (String)(PhaseInterceptorChain.getCurrentMessage().get("product.username")); 
      String userPassword = (String)(PhaseInterceptorChain.getCurrentMessage().get("product.password")); 

      //insert extracted into a org.w3c.dom.Document 
      DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); 
      dbf.setNamespaceAware(true); 
      DocumentBuilder builder = null; 
      org.w3c.dom.Document doc = null; 

      try { 
       builder = dbf.newDocumentBuilder(); 
       InputStream is = convertMessageToInputStream(request); 
       doc = builder.parse(is);     
      } catch (Exception e) { 
       e.printStackTrace(); 
       return null; 
      } 

      NodeList node = doc.getElementsByTagNameNS("*","Security"); 
      node.item(0).getParentNode().removeChild(node.item(0)); 

      // Add extra header to the envelop... 
      ... 

      sourceInvoke = new DOMSource(doc);     

      // 1. Resolve target service based on wsContext 
      QName targetService = new QName(JettyConstants.PersistenceNameSpace,JettyConstants.PersistenceService); 
      QName targetPort = new QName(JettyConstants.PersistenceNameSpace,JettyConstants.PersistencePort); 
      String targetEndpoint = DispatchStarter.getNewVelocityDestination(false)+"/Persistence"; 

    /* ****************************************** INVOKE THE REMOTE SERVER *************************************** */   
      // 2. Create dispatcher 
      Dispatch<Source> dispatcher = createDispatcher(targetService, targetPort, targetEndpoint);  

      // 3. Invoke target service 
      Source response = dispatcher.invoke(sourceInvoke);           

    /* *********************************************************************************************************** */   

      // 4. Return service response to consumer 
      DOMSource domS = toDOMSourceFromSAX((SAXSource)response); 

      //get the doc to modify it: 
      DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); 
      dbf.setNamespaceAware(true); 
      DocumentBuilder builder = null; 
      org.w3c.dom.Document doc = null; 
      builder = dbf.newDocumentBuilder(); 
      doc = (org.w3c.dom.Document) domS.getNode();     

      // 4.1. Take just the body content out of the response received from the server: 
      NodeList body_el = doc.getElementsByTagNameNS("*", "Body").item(0).getChildNodes(); 

      DocumentBuilderFactory docf = DocumentBuilderFactory.newInstance(); 
      Document docnew = docf.newDocumentBuilder().newDocument(); 
      Node newNode = docnew.createElementNS(body_el.item(0).getNamespaceURI(), body_el.item(0).getLocalName()); 
      Node nodeComplete = docnew.adoptNode(body_el.item(0).cloneNode(true));  

      // 4.2. Create the SAXSource to send back to the client through CXF stack 
      ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); 
      Source xmlSource = new DOMSource(nodeComplete); 
      Result outputTarget = new StreamResult(outputStream); 
      TransformerFactory.newInstance().newTransformer().transform(xmlSource, outputTarget); 
      InputStream is = new ByteArrayInputStream(outputStream.toByteArray()); 
      InputSource inputSource = new InputSource(is); 
      SAXSource finalRes = new SAXSource(inputSource);    

      return finalRes; 

     } catch (Exception ex) { 
      ex.printStackTrace(); 
     } 
     return null; 
    } 

    private Dispatch<Source> createDispatcher(QName serviceName, QName portName, String targetEndpoint) { 
     Service service = Service.create(serviceName);   
     String actualBinding = SOAPBinding.SOAP12HTTP_BINDING; 
     service.addPort(portName, actualBinding, targetEndpoint); 
     Dispatch<Source> dispatcher = service.createDispatch(portName, Source.class, 
       Service.Mode.MESSAGE); 
     return dispatcher; 
    } 
} 

PersistenceProvider (điều phối viên) được xuất bản với các WSS4JInterceptors sau đây

Dispatcher WSS4J Dispatcher IN interceptors: 

    Map<String, Object> inProps = new HashMap<String, Object>(); 
    inProps.put(WSHandlerConstants.ACTION, "UsernameToken Timestamp Signature Encrypt"); 
    inProps.put("passwordType",   "PasswordText"); 
    ... 

Dispatcher WSS4J Dispatcher OUT interceptors: 

    protected static final String WSU_NS = 
     "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"; 

    protected static final String SOAP_NS = "http://www.w3.org/2003/05/soap-envelope"; 
    protected static final String WSA_NS = "http://www.w3.org/2005/08/addressing"; 

    outProps.put(WSHandlerConstants.ACTION, "Timestamp Signature Encrypt"); 
    outProps.put("passwordType",   "PasswordText"); 
    ... 
    outProps.put("encryptionParts",   "{Content}{"+SOAP_NS+"}Body"); 
    ... 
    outProps.put("signatureParts",   "{Element}{" + WSU_NS + "}Timestamp;" + 
         "{Element}{"+SOAP_NS+"}Body;" + 
         "{Element}{"+WSA_NS+"}Action;" + 
         "{Element}{"+WSA_NS+"}MessageID;" + 
         "{Element}{"+WSA_NS+"}To;" + 
         "{Element}{"+WSA_NS+"}RelatesTo"); 

và với WSAddressingTính năng được bật. Tôi có thể chuyển hướng các yêu cầu từ khách hàng của tôi đến máy chủ từ xa và tôi nhận được phản hồi từ máy chủ từ xa ở phía người điều phối. Thật không may, khi tôi cố gắng để gửi câu trả lời lại cho khách hàng của tôi (có nghĩa là sau khi tuyên bố trở lại của PersistenceProvider phương pháp # invoke) tôi nhận được ngoại lệ sau đây:

{http://dbproxyservice/}PersistenceService#{http://dispatch/}invoke has thrown exception, unwinding now 
org.apache.cxf.binding.soap.SoapFault: Error creating SOAPMessage 
     at org.apache.cxf.jaxws.interceptors.MessageModeOutInterceptor$MessageModeOutInterceptorInternal.handleMessage(MessageModeOutInterceptor.java:210) 
     at org.apache.cxf.jaxws.interceptors.MessageModeOutInterceptor$MessageModeOutInterceptorInternal.handleMessage(MessageModeOutInterceptor.java:182) 
     at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:263) 
     at org.apache.cxf.interceptor.OutgoingChainInterceptor.handleMessage(OutgoingChainInterceptor.java:77) 
     at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:263) 
     at org.apache.cxf.transport.ChainInitiationObserver.onMessage(ChainInitiationObserver.java:123) 
     at org.apache.cxf.transport.http_jetty.JettyHTTPDestination.serviceRequest(JettyHTTPDestination.java:323) 
     at org.apache.cxf.transport.http_jetty.JettyHTTPDestination.doService(JettyHTTPDestination.java:289) 
     at org.apache.cxf.transport.http_jetty.JettyHTTPHandler.handle(JettyHTTPHandler.java:72) 
     at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:942) 
     at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:878) 
     at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:117) 
     at org.eclipse.jetty.server.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:250) 
     at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:110) 
     at org.eclipse.jetty.server.Server.handle(Server.java:349) 
     at org.eclipse.jetty.server.HttpConnection.handleRequest(HttpConnection.java:441) 
     at org.eclipse.jetty.server.HttpConnection$RequestHandler.content(HttpConnection.java:936) 
     at org.eclipse.jetty.http.HttpParser.parseNext(HttpParser.java:893) 
     at org.eclipse.jetty.http.HttpParser.parseAvailable(HttpParser.java:224) 
     at org.eclipse.jetty.server.AsyncHttpConnection.handle(AsyncHttpConnection.java:52) 
     at org.eclipse.jetty.io.nio.SelectChannelEndPoint.handle(SelectChannelEndPoint.java:586) 
     at org.eclipse.jetty.io.nio.SelectChannelEndPoint$1.run(SelectChannelEndPoint.java:44) 
     at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:598) 
     at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:533) 
     at java.lang.Thread.run(Thread.java:662) 
Caused by: com.ctc.wstx.exc.WstxEOFException: Unexpected EOF in prolog 
at [row,col {unknown-source}]: [1,0] 
     at com.ctc.wstx.sr.StreamScanner.throwUnexpectedEOF(StreamScanner.java:677) 
     at com.ctc.wstx.sr.BasicStreamReader.handleEOF(BasicStreamReader.java:2104) 
     at com.ctc.wstx.sr.BasicStreamReader.nextFromProlog(BasicStreamReader.java:2010) 
     at com.ctc.wstx.sr.BasicStreamReader.next(BasicStreamReader.java:1102) 
     at org.apache.cxf.staxutils.StaxUtils.copy(StaxUtils.java:551) 
     at org.apache.cxf.staxutils.StaxUtils.copy(StaxUtils.java:513) 
     at org.apache.cxf.staxutils.StaxUtils.copy(StaxUtils.java:467) 
     at org.apache.cxf.jaxws.interceptors.MessageModeOutInterceptor$MessageModeOutInterceptorInternal.handleMessage(MessageModeOutInterceptor.java:204) 
     ... 24 more 
[10Dec 18:59:51,881] ([email protected]) WARN PhaseInterceptorChain - Interceptor for {http://dbproxyservice/}PersistenceService#{http://dispatch/}invoke has thrown exception, unwinding now 
java.lang.NullPointerException 
     at org.apache.cxf.ws.addressing.ContextUtils.hasEmptyAction(ContextUtils.java:358) 
     at org.apache.cxf.ws.addressing.MAPAggregator.assembleGeneric(MAPAggregator.java:686) 
     at org.apache.cxf.ws.addressing.MAPAggregator.aggregate(MAPAggregator.java:660) 
     at org.apache.cxf.ws.addressing.MAPAggregator.mediate(MAPAggregator.java:515) 
     at org.apache.cxf.ws.addressing.MAPAggregator.handleMessage(MAPAggregator.java:228) 
     at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:263) 
     at org.apache.cxf.interceptor.AbstractFaultChainInitiatorObserver.onMessage(AbstractFaultChainInitiatorObserver.java:107) 
     at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:323) 
     at org.apache.cxf.interceptor.OutgoingChainInterceptor.handleMessage(OutgoingChainInterceptor.java:77) 
     at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:263) 
     at org.apache.cxf.transport.ChainInitiationObserver.onMessage(ChainInitiationObserver.java:123) 
     at org.apache.cxf.transport.http_jetty.JettyHTTPDestination.serviceRequest(JettyHTTPDestination.java:323) 
     at org.apache.cxf.transport.http_jetty.JettyHTTPDestination.doService(JettyHTTPDestination.java:289) 
     at org.apache.cxf.transport.http_jetty.JettyHTTPHandler.handle(JettyHTTPHandler.java:72) 
     at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:942) 
     at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:878) 
     at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:117) 
     at org.eclipse.jetty.server.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:250) 
     at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:110) 
     at org.eclipse.jetty.server.Server.handle(Server.java:349) 
     at org.eclipse.jetty.server.HttpConnection.handleRequest(HttpConnection.java:441) 
     at org.eclipse.jetty.server.HttpConnection$RequestHandler.content(HttpConnection.java:936) 
     at org.eclipse.jetty.http.HttpParser.parseNext(HttpParser.java:893) 
     at org.eclipse.jetty.http.HttpParser.parseAvailable(HttpParser.java:224) 
     at org.eclipse.jetty.server.AsyncHttpConnection.handle(AsyncHttpConnection.java:52) 
     at org.eclipse.jetty.io.nio.SelectChannelEndPoint.handle(SelectChannelEndPoint.java:586) 
     at org.eclipse.jetty.io.nio.SelectChannelEndPoint$1.run(SelectChannelEndPoint.java:44) 
     at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:598) 
     at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:533) 
     at java.lang.Thread.run(Thread.java:662) 

Bạn có bất cứ gợi ý để tránh lỗi này? Cụ thể, tôi phải làm gì để gửi phản hồi gọi lại cho khách hàng thông qua ngăn xếp CXF? Có đúng để loại bỏ tất cả các tiêu đề nhận được từ máy chủ từ xa tại điểm 4 của PersistenceProvider # gọi ở trên không? Tôi đã làm điều đó vì tôi nghĩ rằng CXF của người điều khiển máy bay đánh chặn sẽ xây dựng phong bì từ đầu xung quanh cơ thể. Đúng không?

Cảm ơn bạn!

Trả lời

1

Gotcha! Điều mà mẹo làm là chuyển đổi javax.xml.transform.Source được trả về bởi phương thức gọi trong PersistenceProvider (dispatcher) thành một DOMSource. Điều đó cho phép CXF làm đầy cơ thể phong bì xà phòng đi một cách chính xác.

Sự cố được giải quyết. Câu chuyện đầy đủ here!

Các vấn đề liên quan