You are viewing a plain text version of this content. The canonical link for it is here.
Posted to java-dev@axis.apache.org by sc...@apache.org on 2007/02/14 02:37:17 UTC

svn commit: r507347 - in /webservices/axis2/trunk/java/modules/jaxws: src/org/apache/axis2/jaxws/message/ src/org/apache/axis2/jaxws/message/impl/ src/org/apache/axis2/jaxws/server/ src/org/apache/axis2/jaxws/spi/ test/org/apache/axis2/jaxws/message/

Author: scheu
Date: Tue Feb 13 17:37:16 2007
New Revision: 507347

URL: http://svn.apache.org/viewvc?view=rev&rev=507347
Log:
AXIS2-2166
Contributor: Rich Scheuerle
Improvements to the JAX-WS message processing to 'support' persistance of request message by outbound handlers. 

Added:
    webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/spi/Constants.java
Modified:
    webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/message/Message.java
    webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/message/impl/BlockImpl.java
    webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/message/impl/MessageImpl.java
    webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/server/EndpointController.java
    webservices/axis2/trunk/java/modules/jaxws/test/org/apache/axis2/jaxws/message/MessageTests.java

Modified: webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/message/Message.java
URL: http://svn.apache.org/viewvc/webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/message/Message.java?view=diff&rev=507347&r1=507346&r2=507347
==============================================================================
--- webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/message/Message.java (original)
+++ webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/message/Message.java Tue Feb 13 17:37:16 2007
@@ -106,4 +106,16 @@
      * @param mhs MimeHeaders
      */
     public void setMimeHeaders(MimeHeaders mhs);
+    
+    /**
+     * Indicate that this message is passed the pivot point.
+     * For example, this is set in the JAX-WS Dispatcher
+     * to indicate 
+     */
+    public void setPostPivot();
+    
+    /**
+     * @return true if post pivot
+     */
+    public boolean isPostPivot();
 }

Modified: webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/message/impl/BlockImpl.java
URL: http://svn.apache.org/viewvc/webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/message/impl/BlockImpl.java?view=diff&rev=507347&r1=507346&r2=507347
==============================================================================
--- webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/message/impl/BlockImpl.java (original)
+++ webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/message/impl/BlockImpl.java Tue Feb 13 17:37:16 2007
@@ -17,6 +17,7 @@
 package org.apache.axis2.jaxws.message.impl;
 
 import java.io.OutputStream;
+import java.io.StringReader;
 import java.io.Writer;
 
 import javax.xml.namespace.QName;
@@ -37,6 +38,7 @@
 import org.apache.axis2.jaxws.message.XMLPart;
 import org.apache.axis2.jaxws.message.factory.BlockFactory;
 import org.apache.axis2.jaxws.message.util.Reader2Writer;
+import org.apache.axis2.jaxws.spi.Constants;
 import org.apache.axis2.jaxws.utility.JavaUtils;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
@@ -186,7 +188,12 @@
 	public XMLStreamReader getXMLStreamReader(boolean consume) throws XMLStreamException, WebServiceException {
 		XMLStreamReader newReader = null;
 		if (consumed) {
-			throw ExceptionFactory.makeWebServiceException(Messages.getMessage("BlockImplErr1", this.getClass().getName()));
+		    // In some scenarios, the message is written out after the service instance is invoked.
+            // In these situations, it is preferable to simply ignore this block.
+            if (this.getParent() != null && getParent().isPostPivot()) {
+                return _postPivot_getXMLStreamReader();
+            }
+            throw ExceptionFactory.makeWebServiceException(Messages.getMessage("BlockImplErr1", this.getClass().getName()));
 		}
 		if (omElement != null) {
 			if (consume) {
@@ -294,6 +301,11 @@
 
 	public void outputTo(XMLStreamWriter writer, boolean consume) throws XMLStreamException, WebServiceException {
 		if (consumed) {
+            // In some scenarios, the message is written out after the service instance is invoked.
+            // In these situations, it is preferable to simply ignore this block.
+            if (this.getParent() != null && getParent().isPostPivot()) {
+                _postPivot_outputTo(writer);
+            }
 			throw ExceptionFactory.makeWebServiceException(Messages.getMessage("BlockImplErr1", this.getClass().getName()));
 		}
 		if (omElement != null) {
@@ -309,6 +321,40 @@
 		setConsumed(consume);
 		return;
 	}
+    
+    /**
+     * Called if we have passed the pivot point but someone wants to output the block.
+     * The actual block implementation may choose to override this setting
+     */
+    protected void _postPivot_outputTo(XMLStreamWriter writer) throws XMLStreamException, WebServiceException {
+        if (log.isDebugEnabled()) {
+            QName theQName = isQNameAvailable() ? getQName() : new QName("unknown");
+            log.debug("The Block for " + theQName + " is already consumed and therefore it is not written.");
+            log.debug("If you need this block preserved, please set the " + Constants.SAVE_REQUEST_MSG + " property on the MessageContext.");
+        }
+        return;
+    }
+    
+    /**
+     * Called if we have passed the pivot point but someone wants to output the block.
+     * The actual block implementation may choose to override this setting.
+     */
+    protected XMLStreamReader _postPivot_getXMLStreamReader() throws XMLStreamException, WebServiceException {
+        if (log.isDebugEnabled()) {
+            QName theQName = isQNameAvailable() ? getQName() : new QName("unknown");
+            log.debug("The Block for " + theQName + " is already consumed and therefore it is only partially read.");
+            log.debug("If you need this block preserved, please set the " + Constants.SAVE_REQUEST_MSG + " property on the MessageContext.");
+        }
+        QName qName = getQName();
+        String text = "";
+        if (qName.getNamespaceURI().length() > 0) {
+            text = "<prefix:" + qName.getLocalPart() + " xmlns:prefix='" + qName.getNamespaceURI() + "'/>";
+        } else {
+            text = "<" + qName.getLocalPart() + "/>";
+        }
+        StringReader sr = new StringReader(text);
+        return StAXUtils.createXMLStreamReader(sr);
+    }
 
 	/**
 	 * @return true if the representation of the block is currently a business object.

Modified: webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/message/impl/MessageImpl.java
URL: http://svn.apache.org/viewvc/webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/message/impl/MessageImpl.java?view=diff&rev=507347&r1=507346&r2=507347
==============================================================================
--- webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/message/impl/MessageImpl.java (original)
+++ webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/message/impl/MessageImpl.java Tue Feb 13 17:37:16 2007
@@ -69,6 +69,8 @@
     boolean mtomEnabled;
     private MimeHeaders mimeHeaders = new MimeHeaders(); 
     
+    private boolean postPivot = false;
+    
 	// Constants
 	private static final String SOAP11_ENV_NS = "http://schemas.xmlsoap.org/soap/envelope/";
 	private static final String SOAP12_ENV_NS = "http://www.w3.org/2003/05/soap-envelope";
@@ -426,6 +428,14 @@
 
     public void setBodyBlock(Block block) throws WebServiceException {
         xmlPart.setBodyBlock(block);
+    }
+
+    public void setPostPivot() {
+        this.postPivot = true;
+    }
+    
+    public boolean isPostPivot() {
+        return postPivot;
     }
 
 }

Modified: webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/server/EndpointController.java
URL: http://svn.apache.org/viewvc/webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/server/EndpointController.java?view=diff&rev=507347&r1=507346&r2=507347
==============================================================================
--- webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/server/EndpointController.java (original)
+++ webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/server/EndpointController.java Tue Feb 13 17:37:16 2007
@@ -17,9 +17,17 @@
 package org.apache.axis2.jaxws.server;
 
 import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+import javax.xml.ws.WebServiceException;
+
+import java.io.StringReader;
 import java.security.PrivilegedExceptionAction;
 import java.security.PrivilegedActionException;
 
+import org.apache.axiom.om.impl.builder.StAXBuilder;
+import org.apache.axiom.om.util.StAXUtils;
+import org.apache.axiom.soap.SOAPEnvelope;
+import org.apache.axiom.soap.impl.builder.StAXSOAPModelBuilder;
 import org.apache.axis2.description.AxisService;
 import org.apache.axis2.description.Parameter;
 import org.apache.axis2.java.security.AccessController;
@@ -43,6 +51,7 @@
 import org.apache.axis2.jaxws.server.dispatcher.factory.EndpointDispatcherFactory;
 import org.apache.axis2.jaxws.server.endpoint.lifecycle.EndpointLifecycleManager;
 import org.apache.axis2.jaxws.server.endpoint.lifecycle.factory.EndpointLifecycleManagerFactory;
+import org.apache.axis2.jaxws.spi.Constants;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 
@@ -112,14 +121,33 @@
 		MessageContext responseMsgContext = null;
 		
 		try {
+            // Get the service instance.  This will run the @PostConstruct code.
 			EndpointLifecycleManager elm = createEndpointlifecycleManager();
 			Object serviceInstance = elm.createServiceInstance(requestMsgCtx, implClass);
-			EndpointDispatcher dispatcher = getEndpointDispatcher(implClass, serviceInstance);
+			
+            // The application handlers and dispatcher invoke will 
+            // modify/destroy parts of the message.  Make sure to save
+            // the request message if appropriate.
+            saveRequestMessage(requestMsgCtx);
+            
+            // @TODO Invoke inbound application handlers.
+ 
+            // Dispatch to the 
+            EndpointDispatcher dispatcher = getEndpointDispatcher(implClass, serviceInstance); 
+            try {
+                responseMsgContext = dispatcher.invoke(requestMsgCtx);
+            } finally {
+                // Passed pivot point
+                requestMsgCtx.getMessage().setPostPivot();
+            }
+            
+            // @TODO Invoke outbound application handlers
             
-			responseMsgContext = dispatcher.invoke(requestMsgCtx);
         } catch (Exception e) {
             // TODO for now, throw it.  We probably should try to make an XMLFault object and set it on the message
             throw ExceptionFactory.makeWebServiceException(e);
+        } finally {
+            restoreRequestMessage(requestMsgCtx);
         }
 
 		// The response MessageContext should be set on the InvocationContext
@@ -262,5 +290,56 @@
            // TODO for now, throw it.  We probably should try to make an XMLFault object and set it on the message
            throw ExceptionFactory.makeWebServiceException(e);
        }
+   }
+   
+  /**  
+   * Save the request message if indicated by the SAVE_REQUEST_MSG property
+   * @param requestMsgContext
+   */
+   private void saveRequestMessage(MessageContext requestMsgContext) {
+       
+       // TESTING...FORCE SAVING THE REQUEST MESSAGE
+       // requestMsgContext.getAxisMessageContext().setProperty(Constants.SAVE_REQUEST_MSG, Boolean.TRUE);
+       // END TESTING
+       
+       Boolean value = (Boolean)
+           requestMsgContext.getAxisMessageContext().getProperty(Constants.SAVE_REQUEST_MSG);
+       if (value != null && value == Boolean.TRUE) {
+           // REVIEW: This does not properly account for attachments.
+           Message m = requestMsgContext.getMessage();
+           String savedMsg = m.getAsOMElement().toString();
+           requestMsgContext.getAxisMessageContext().setProperty(Constants.SAVED_REQUEST_MSG_TEXT, savedMsg);
+       }
+   }
+   
+  /**
+   * Restore the request message from the saved message text
+   * @param requestMsgContext
+   */
+   private void restoreRequestMessage(MessageContext requestMsgContext) {
+       
+       Boolean value = (Boolean)
+           requestMsgContext.getAxisMessageContext().getProperty(Constants.SAVE_REQUEST_MSG);
+       if (value != null && value == Boolean.TRUE) {
+           // REVIEW: This does not properly account for attachments.
+           String savedMsg = (String) requestMsgContext.getAxisMessageContext().getProperty(Constants.SAVED_REQUEST_MSG_TEXT);
+           if (savedMsg != null && savedMsg.length() > 0) {               
+               try {
+                   StringReader sr = new StringReader(savedMsg);
+                   XMLStreamReader xmlreader = StAXUtils.createXMLStreamReader(sr);
+                   MessageFactory mf = (MessageFactory) 
+                       FactoryRegistry.getFactory(MessageFactory.class);
+                   Message msg = mf.createFrom(xmlreader);
+                   requestMsgContext.setMessage(msg);
+               } catch (Throwable e) {
+                   ExceptionFactory.makeWebServiceException(e);
+               }
+           }
+       }
+       
+       // TESTING....SIMULATE A PERSIST OF THE REQUEST MESSAGE
+       // String text = requestMsgContext.getMessage().getAsOMElement().toString();
+       // System.out.println("Persist Message" + text);
+       // END TESTING
    }
 }

Added: webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/spi/Constants.java
URL: http://svn.apache.org/viewvc/webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/spi/Constants.java?view=auto&rev=507347
==============================================================================
--- webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/spi/Constants.java (added)
+++ webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/spi/Constants.java Tue Feb 13 17:37:16 2007
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *      
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.axis2.jaxws.spi;
+
+/**
+ * JAXWS SPI Constants
+ */
+public class Constants {
+    
+    // ----------------------------
+    // MessageContext Property Keys
+    // ----------------------------
+    
+    // Value = Boolean
+    // Usage: Setting this property to true will cause the entire request message
+    //   to be saved and restored. A reliable messaging inbound handler should set 
+    //   this flag if the entire message should be saved.  Setting this flag will substantially
+    //   degrade performance.
+    //
+    //   The default is to not save the entire message.  After server dispatch processing, the 
+    //   body of the request message will not be available.  This is acceptable in most scenarios.
+    //
+    // REVIEW Only honored on the server: Saved before inbound application handler processing and
+    //   restored after outbound application handler processing.
+    //
+    public static final String SAVE_REQUEST_MSG = "org.apache.axis2.jaxws.spi.SAVE_REQUEST_MSG";
+
+    // Value = String
+    // Usage: Value of saved request
+    //
+    public static final String SAVED_REQUEST_MSG_TEXT = "org.apache.axis2.jaxws.spi.SAVED_REQUEST_MSG_TEXT";
+    
+    /**
+     * Intentionally Private
+     */
+    private Constants() { }
+
+}

Modified: webservices/axis2/trunk/java/modules/jaxws/test/org/apache/axis2/jaxws/message/MessageTests.java
URL: http://svn.apache.org/viewvc/webservices/axis2/trunk/java/modules/jaxws/test/org/apache/axis2/jaxws/message/MessageTests.java?view=diff&rev=507347&r1=507346&r2=507347
==============================================================================
--- webservices/axis2/trunk/java/modules/jaxws/test/org/apache/axis2/jaxws/message/MessageTests.java (original)
+++ webservices/axis2/trunk/java/modules/jaxws/test/org/apache/axis2/jaxws/message/MessageTests.java Tue Feb 13 17:37:16 2007
@@ -758,13 +758,28 @@
         assertTrue(newText.contains("Body"));
     }
     
+    private final int NO_PERSIST       = 0;
+    private final int PERSIST         = 1;
+    private final int SAVE_AND_PERSIST = 2;
     public void testJAXBInflow_soap11() throws Exception {
-		_testJAXBInflow(sampleJAXBEnvelope11);
+		_testJAXBInflow(sampleJAXBEnvelope11, NO_PERSIST);
 	}
 	public void testJAXBInflow_soap12() throws Exception {
-		_testJAXBInflow(sampleJAXBEnvelope12);
+		_testJAXBInflow(sampleJAXBEnvelope12, NO_PERSIST);
 	}
-	public void _testJAXBInflow(String sampleJAXBEnvelope) throws Exception {
+    public void testJAXBInflow_soap11_withPersist() throws Exception {
+        _testJAXBInflow(sampleJAXBEnvelope11, PERSIST);
+    }
+    public void testJAXBInflow_soap12_withPersist() throws Exception {
+        _testJAXBInflow(sampleJAXBEnvelope12, PERSIST);
+    }
+    public void testJAXBInflow_soap11_withSaveAndPersist() throws Exception {
+        _testJAXBInflow(sampleJAXBEnvelope11, SAVE_AND_PERSIST);
+    }
+    public void testJAXBInflow_soap12_withSaveAndPersist() throws Exception {
+        _testJAXBInflow(sampleJAXBEnvelope12, SAVE_AND_PERSIST);
+    }
+	public void _testJAXBInflow(String sampleJAXBEnvelope, int persist) throws Exception {
         // Create a SOAP OM out of the sample incoming XML.  This
         // simulates what Axis2 will be doing with the inbound message. 
         StringReader sr = new StringReader(sampleJAXBEnvelope);
@@ -784,6 +799,12 @@
         assertTrue("XMLPart Representation is " + m.getXMLPartContentType(),
                     "OM".equals(m.getXMLPartContentType()));
         
+        String saveMsgText = "";
+        if (persist == SAVE_AND_PERSIST) {
+            // Simulate saving the message so that it can be fully rebuilt.
+            saveMsgText = m.getAsOMElement().toString();
+        }
+        
         // Get the BlockFactory
         JAXBBlockFactory bf = (JAXBBlockFactory)
             FactoryRegistry.getFactory(JAXBBlockFactory.class);
@@ -805,6 +826,17 @@
         // Get the business object from the block, which should be a 
         // JAX-B object
         Object bo = b.getBusinessObject(true);
+        m.setPostPivot();
+        
+        // Simulate restoring the message
+        if (persist == SAVE_AND_PERSIST) {
+            sr = new StringReader(saveMsgText);
+            XMLStreamReader saveMsgReader = inputFactory.createXMLStreamReader(sr);
+            builder = new StAXSOAPModelBuilder(saveMsgReader, null);
+            omElement = builder.getSOAPEnvelope();
+            m = mf.createFrom(omElement);
+        } 
+        
         
         // Check to make sure the right object was returned
         assertNotNull(bo);
@@ -814,6 +846,22 @@
         EchoStringResponse esr = (EchoStringResponse) bo;
         assertNotNull(esr.getEchoStringReturn());
         assertTrue(esr.getEchoStringReturn().equals("sample return value"));
+        
+        // Simulate outbound
+        if (persist == PERSIST) {
+            String persistMsg = m.getAsOMElement().toString();
+            // We should be able to persist the message, but the persisted message WON'T contain the echoStringResponse contents
+            assertTrue(persistMsg.contains("Body"));
+            assertTrue(persistMsg.contains("echoStringResponse"));
+            assertTrue(!persistMsg.contains("sample return value"));
+            
+        } else if (persist == SAVE_AND_PERSIST) {
+            String persistMsg = m.getAsOMElement().toString();
+            // We should be able to persist the message, and the persisted message WILL contain the echoStringResponse contents
+            assertTrue(persistMsg.contains("Body"));
+            assertTrue(persistMsg.contains("echoStringResponse"));
+            assertTrue(persistMsg.contains("sample return value"));
+        }
     }
     
     



---------------------------------------------------------------------
To unsubscribe, e-mail: axis-cvs-unsubscribe@ws.apache.org
For additional commands, e-mail: axis-cvs-help@ws.apache.org