/*
* 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.client;
import org.apache.axis2.context.ConfigurationContext;
import org.apache.axis2.context.MessageContext;
import org.apache.axis2.description.AxisService;
import org.apache.axis2.description.AxisServiceGroup;
import org.apache.axis2.description.Parameter;
import org.apache.axis2.description.WSDL11ToAllAxisServicesBuilder;
import org.apache.axis2.jaxws.description.EndpointDescription;
import org.apache.axis2.jaxws.spi.ClientMetadataTest;
import javax.xml.namespace.QName;
import javax.xml.ws.Dispatch;
import javax.xml.ws.Service;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import junit.framework.TestCase;
/**
* Test the serialization of a MessageContext and subsequent deserialization to ensure the
* JAXWS and Axis2 objects for the relevant ports are hooked back up correctly. In particluar,
* make sure the AxisServices can be hooked back up with the MEssageContexts correctly.
*
* This is done as a JAX-WS test rather than an Axis2 test to verify the behavior of ports
* added by JAX-WS, particluarly dynamic ports.
*/
public class PortDeserializationTests extends TestCase {
static final String namespaceURI = "http://client.jaxws.axis2.apache.org";
static final String svcLocalPart = "svcLocalPart";
static final String dynamicPort = "dynamicPort";
static final String bindingID = null;
static final String epr = "http://dummy/endpoint/address";
/**
* Validate that a message context can be serialized and deserialized with the Axis2
* and JAX-WS description objects not being recreated. This is similar to a message
* being serialized and deserialized without the server being stopped.
*/
public void testDynamicPortSingleServiceNoRecreate() {
try {
ClientMetadataTest.installCachingFactory();
QName svc1QN = new QName(namespaceURI + "?1", svcLocalPart);
Service svc1 = Service.create(svc1QN);
QName portQN = new QName(namespaceURI, dynamicPort + "_1");
svc1.addPort(portQN, bindingID, epr);
Dispatch<String> port1 = svc1.createDispatch(portQN, String.class, Service.Mode.PAYLOAD);
// We need to get the AxisService so we can set in on a MessageContext and test
// serialization / deserialization. We do this using NON-Public, INTERNAL SPIs
// since we need to get at the internals of the engine
org.apache.axis2.jaxws.spi.BindingProvider bindingProvider =
(org.apache.axis2.jaxws.spi.BindingProvider) port1;
EndpointDescription endpointDesc = bindingProvider.getEndpointDescription();
AxisService axisService = endpointDesc.getAxisService();
assertNotNull(axisService);
assertEquals(svc1QN.getLocalPart(), axisService.getName());
// Now that the AxisService is setup, create an Axis2 message context, set the
// AxisService on it. Serialize it out then read it back in.
MessageContext msgCtx = new MessageContext();
msgCtx.setAxisService(axisService);
msgCtx.setAxisServiceGroup(axisService.getAxisServiceGroup());
ByteArrayOutputStream baos = serializeMessageContext(msgCtx);
// Read in the message context and activate it, which is required by message
// context deserialization to connect the message context to existing runtime
// objects such as AxisService
MessageContext mcRead = deserializeMessageContext(baos);
ConfigurationContext configContext = endpointDesc.getServiceDescription().getAxisConfigContext();
assertNotNull(configContext);
mcRead.activate(configContext);
AxisService asRead = mcRead.getAxisService();
assertNotNull(asRead);
assertEquals(axisService.getName(), asRead.getName());
assertSame(axisService, asRead);
AxisServiceGroup agRead = mcRead.getAxisServiceGroup();
assertNotNull(agRead);
// This keeps the port from being GC'd and causing the AxisService to be freed
// before the test method completes.
assertNotNull(port1);
} catch (Exception t) {
t.printStackTrace();
fail("Caught throwable " + t);
} finally {
ClientMetadataTest.restoreOriginalFactory();
}
}
/**
* Validate that a message context can be serialized and deserialized with the Axis2
* and JAX-WS description objects not being recreated. This is similar to a message
* being serialized and deserialized without the server being stopped.
*
* This test uses two services with different namespaces, each with a dynamic port of the
* same name.
*/
public void testDynamicPortMultipleServiceNoRecreate() {
try {
ClientMetadataTest.installCachingFactory();
QName svc1QN = new QName(namespaceURI + "?1", svcLocalPart);
QName svc2QN = new QName(namespaceURI + "?2", svcLocalPart);
Service svc1 = Service.create(svc1QN);
Service svc2 = Service.create(svc2QN);
// Create the same port under the two different services. Each port gets a unique
// EPR so it will cause a new port to be created (rather than shared) which in
// turn causes a new AxisService to be crated.
QName portQN = new QName(namespaceURI, dynamicPort + "_1");
svc1.addPort(portQN, bindingID, epr + "1");
Dispatch<String> port1 = svc1.createDispatch(portQN, String.class, Service.Mode.PAYLOAD);
svc2.addPort(portQN, bindingID, epr + "2");
Dispatch<String> port2 = svc2.createDispatch(portQN, String.class, Service.Mode.PAYLOAD);
// We need to get the AxisService so we can set in on a MessageContext and test
// serialization / deserialization. We do this using NON-Public, INTERNAL SPIs
// since we need to get at the internals of the engine
// Check the AxisService created for both ports.
org.apache.axis2.jaxws.spi.BindingProvider bindingProvider1 =
(org.apache.axis2.jaxws.spi.BindingProvider) port1;
EndpointDescription endpointDesc1 = bindingProvider1.getEndpointDescription();
AxisService axisService1 = endpointDesc1.getAxisService();
assertNotNull(axisService1);
assertEquals(svc1QN.getLocalPart(), axisService1.getName());
org.apache.axis2.jaxws.spi.BindingProvider bindingProvider2 =
(org.apache.axis2.jaxws.spi.BindingProvider) port2;
EndpointDescription endpointDesc2 = bindingProvider2.getEndpointDescription();
AxisService axisService2 = endpointDesc2.getAxisService();
assertNotNull(axisService2);
assertNotSame(axisService1, axisService2);
// The 2nd AxisService created gets a unique ID appended to the name
String baseName = svc2QN.getLocalPart();
assertFalse(baseName.equals(axisService2.getName()));
assertTrue(axisService2.getName().startsWith(baseName));
// Now that the AxisService is setup, create two Axis2 message contexts, set the
// AxisServices on them. Serialize them out
MessageContext msgCtx1 = new MessageContext();
msgCtx1.setAxisService(axisService1);
msgCtx1.setAxisServiceGroup(axisService1.getAxisServiceGroup());
ByteArrayOutputStream baos1 = serializeMessageContext(msgCtx1);
MessageContext msgCtx2 = new MessageContext();
msgCtx2.setAxisService(axisService2);
msgCtx2.setAxisServiceGroup(axisService2.getAxisServiceGroup());
ByteArrayOutputStream baos2 = serializeMessageContext(msgCtx2);
// Read in the message contexts and activate them, which is required by message
// context deserialization to connect the message context to existing runtime
// objects such as AxisService
// Note that we do them in reverse order to make sure the logic is order-independent
// Do the same for the second Message Context
MessageContext mcRead2 = deserializeMessageContext(baos2);
ConfigurationContext configContext2 = endpointDesc2.getServiceDescription().getAxisConfigContext();
assertNotNull(configContext2);
mcRead2.activate(configContext2);
AxisService asRead2 = mcRead2.getAxisService();
assertNotNull(asRead2);
assertEquals(axisService2.getName(), asRead2.getName());
assertSame(axisService2, asRead2);
AxisServiceGroup agRead2 = mcRead2.getAxisServiceGroup();
assertNotNull(agRead2);
MessageContext mcRead1 = deserializeMessageContext(baos1);
ConfigurationContext configContext1 = endpointDesc1.getServiceDescription().getAxisConfigContext();
assertSame(configContext1, configContext2);
assertNotNull(configContext1);
mcRead1.activate(configContext1);
AxisService asRead1 = mcRead1.getAxisService();
assertNotNull(asRead1);
assertEquals(axisService1.getName(), asRead1.getName());
assertSame(axisService1, asRead1);
AxisServiceGroup agRead1 = mcRead1.getAxisServiceGroup();
assertNotNull(agRead1);
// These keep the ports from being GC'd before the test method completes and
// freeing up the AxisServices
assertNotNull(port1);
assertNotNull(port2);
} catch (Exception t) {
t.printStackTrace();
fail("Caught throwable " + t);
} finally {
ClientMetadataTest.restoreOriginalFactory();
}
}
/**
* Validate that a message context can be serialized and deserialized with the Axis2
* and JAX-WS description objects not being recreated. This is similar to a message
* being serialized and deserialized without the server being stopped.
*
* This test uses two services with the same namespaces, each with a dynamic port of the
* same name.
*/
public void testDynamicPortMultipleServiceNoRecreateSameNS() {
try {
ClientMetadataTest.installCachingFactory();
QName svc1QN = new QName(namespaceURI + "?1", svcLocalPart);
QName svc2QN = new QName(namespaceURI + "?1", svcLocalPart);
Service svc1 = Service.create(svc1QN);
Service svc2 = Service.create(svc2QN);
// Create the same port under the two different services. Each port gets a unique
// EPR so it will cause a new port to be created (rather than shared) which in
// turn causes a new AxisService to be crated.
QName portQN = new QName(namespaceURI, dynamicPort + "_1");
svc1.addPort(portQN, bindingID, epr + "1");
Dispatch<String> port1 = svc1.createDispatch(portQN, String.class, Service.Mode.PAYLOAD);
svc2.addPort(portQN, bindingID, epr + "2");
Dispatch<String> port2 = svc2.createDispatch(portQN, String.class, Service.Mode.PAYLOAD);
// We need to get the AxisService so we can set in on a MessageContext and test
// serialization / deserialization. We do this using NON-Public, INTERNAL SPIs
// since we need to get at the internals of the engine
// Check the AxisService created for both ports.
org.apache.axis2.jaxws.spi.BindingProvider bindingProvider1 =
(org.apache.axis2.jaxws.spi.BindingProvider) port1;
EndpointDescription endpointDesc1 = bindingProvider1.getEndpointDescription();
AxisService axisService1 = endpointDesc1.getAxisService();
assertNotNull(axisService1);
assertEquals(svc1QN.getLocalPart(), axisService1.getName());
org.apache.axis2.jaxws.spi.BindingProvider bindingProvider2 =
(org.apache.axis2.jaxws.spi.BindingProvider) port2;
EndpointDescription endpointDesc2 = bindingProvider2.getEndpointDescription();
AxisService axisService2 = endpointDesc2.getAxisService();
assertNotNull(axisService2);
assertNotSame(axisService1, axisService2);
// The 2nd AxisService created gets a unique ID appended to the name
String baseName = svc2QN.getLocalPart();
assertFalse(baseName.equals(axisService2.getName()));
assertTrue(axisService2.getName().startsWith(baseName));
// Now that the AxisService is setup, create two Axis2 message contexts, set the
// AxisServices on them. Serialize them out
MessageContext msgCtx1 = new MessageContext();
msgCtx1.setAxisService(axisService1);
msgCtx1.setAxisServiceGroup(axisService1.getAxisServiceGroup());
ByteArrayOutputStream baos1 = serializeMessageContext(msgCtx1);
MessageContext msgCtx2 = new MessageContext();
msgCtx2.setAxisService(axisService2);
msgCtx2.setAxisServiceGroup(axisService2.getAxisServiceGroup());
ByteArrayOutputStream baos2 = serializeMessageContext(msgCtx2);
// Read in the message contexts and activate them, which is required by message
// context deserialization to connect the message context to existing runtime
// objects such as AxisService
MessageContext mcRead1 = deserializeMessageContext(baos1);
ConfigurationContext configContext1 = endpointDesc1.getServiceDescription().getAxisConfigContext();
assertNotNull(configContext1);
mcRead1.activate(configContext1);
AxisService asRead1 = mcRead1.getAxisService();
assertNotNull(asRead1);
assertEquals(axisService1.getName(), asRead1.getName());
assertSame(axisService1, asRead1);
AxisServiceGroup agRead1 = mcRead1.getAxisServiceGroup();
assertNotNull(agRead1);
// Do the same for the second Message Context
MessageContext mcRead2 = deserializeMessageContext(baos2);
ConfigurationContext configContext2 = endpointDesc2.getServiceDescription().getAxisConfigContext();
assertSame(configContext1, configContext2);
assertNotNull(configContext2);
mcRead2.activate(configContext2);
AxisService asRead2 = mcRead2.getAxisService();
assertNotNull(asRead2);
assertEquals(axisService2.getName(), asRead2.getName());
assertSame(axisService2, asRead2);
AxisServiceGroup agRead2 = mcRead2.getAxisServiceGroup();
assertNotNull(agRead2);
// These keep the ports from being GC'd before the test method completes and
// freeing up the AxisServices
assertNotNull(port1);
assertNotNull(port2);
} catch (Exception t) {
t.printStackTrace();
fail("Caught throwable " + t);
} finally {
ClientMetadataTest.restoreOriginalFactory();
}
}
/**
* Validate that a message context can be serialized and deserialized with the Axis2
* and JAX-WS description objects being recreated before the deserialization. This is
* similar to a message being serialized, the server being restarted and then the
* messgage being deserialized. In this case it must be hooked up with new instances
* of what should be identical objects such as AxisServices.
*/
public void testDynamicPortMultipleServiceWithRecreate() {
try {
ClientMetadataTest.installCachingFactory();
QName svc1QN = new QName(namespaceURI + "?1", svcLocalPart);
QName svc2QN = new QName(namespaceURI + "?2", svcLocalPart);
QName portQN = new QName(namespaceURI, dynamicPort + "_1");
Service svc1 = Service.create(svc1QN);
Service svc2 = Service.create(svc2QN);
// Create the same port under the two different services. Each port gets a unique
// EPR so it will cause a new port to be created (rather than shared) which in
// turn causes a new AxisService to be crated.
svc1.addPort(portQN, bindingID, epr + "1");
Dispatch<String> port1 = svc1.createDispatch(portQN, String.class, Service.Mode.PAYLOAD);
svc2.addPort(portQN, bindingID, epr + "2");
Dispatch<String> port2 = svc2.createDispatch(portQN, String.class, Service.Mode.PAYLOAD);
// We need to get the AxisService so we can set in on a MessageContext and test
// serialization / deserialization. We do this using NON-Public, INTERNAL SPIs
// since we need to get at the internals of the engine
// Check the AxisService created for both ports.
org.apache.axis2.jaxws.spi.BindingProvider bindingProvider1 =
(org.apache.axis2.jaxws.spi.BindingProvider) port1;
EndpointDescription endpointDesc1 = bindingProvider1.getEndpointDescription();
AxisService axisService1 = endpointDesc1.getAxisService();
assertNotNull(axisService1);
assertEquals(svc1QN.getLocalPart(), axisService1.getName());
org.apache.axis2.jaxws.spi.BindingProvider bindingProvider2 =
(org.apache.axis2.jaxws.spi.BindingProvider) port2;
EndpointDescription endpointDesc2 = bindingProvider2.getEndpointDescription();
AxisService axisService2 = endpointDesc2.getAxisService();
assertNotNull(axisService2);
assertNotSame(axisService1, axisService2);
// The 2nd AxisService created gets a unique ID appended to the name
String baseName = svc2QN.getLocalPart();
assertFalse(baseName.equals(axisService2.getName()));
assertTrue(axisService2.getName().startsWith(baseName));
// Now that the AxisService is setup, create two Axis2 message contexts, set the
// AxisServices on them. Serialize them out
MessageContext msgCtx1 = new MessageContext();
msgCtx1.setAxisService(axisService1);
msgCtx1.setAxisServiceGroup(axisService1.getAxisServiceGroup());
ByteArrayOutputStream baos1 = serializeMessageContext(msgCtx1);
MessageContext msgCtx2 = new MessageContext();
msgCtx2.setAxisService(axisService2);
msgCtx2.setAxisServiceGroup(axisService2.getAxisServiceGroup());
ByteArrayOutputStream baos2 = serializeMessageContext(msgCtx2);
// Now cause the runtime objects to be recreated. Do this by forcing a release
// of both Service instances, which will also release the runtime objects
// such as the AxisService underneath them. Then recreate the ports
org.apache.axis2.jaxws.spi.ServiceDelegate.releaseService(svc1);
org.apache.axis2.jaxws.spi.ServiceDelegate.releaseService(svc2);
Service svc1_redo = Service.create(svc1QN);
Service svc2_redo = Service.create(svc2QN);
svc1_redo.addPort(portQN, bindingID, epr + "1");
Dispatch<String> port1_redo = svc1_redo.createDispatch(portQN, String.class, Service.Mode.PAYLOAD);
svc2_redo.addPort(portQN, bindingID, epr + "2");
Dispatch<String> port2_redo = svc2_redo.createDispatch(portQN, String.class, Service.Mode.PAYLOAD);
org.apache.axis2.jaxws.spi.BindingProvider bindingProvider1_redo =
(org.apache.axis2.jaxws.spi.BindingProvider) port1_redo;
EndpointDescription endpointDesc1_redo = bindingProvider1_redo.getEndpointDescription();
AxisService axisService1_redo = endpointDesc1_redo.getAxisService();
assertNotNull(axisService1_redo);
assertEquals(baseName, axisService1_redo.getName());
org.apache.axis2.jaxws.spi.BindingProvider bindingProvider2_redo =
(org.apache.axis2.jaxws.spi.BindingProvider) port2_redo;
EndpointDescription endpointDesc2_redo = bindingProvider2_redo.getEndpointDescription();
AxisService axisService2_redo = endpointDesc2_redo.getAxisService();
assertNotNull(axisService2_redo);
assertNotSame(axisService1_redo, axisService2_redo);
Parameter svcQNParam1_redo = axisService1_redo.getParameter(WSDL11ToAllAxisServicesBuilder.WSDL_SERVICE_QNAME);
assertEquals(svc1QN, svcQNParam1_redo.getValue());
// The 2nd AxisService created gets a unique ID appended to the name
assertFalse(baseName.equals(axisService2_redo.getName()));
assertTrue(axisService2_redo.getName().startsWith(baseName));
Parameter svcQNParam2_redo = axisService2_redo.getParameter(WSDL11ToAllAxisServicesBuilder.WSDL_SERVICE_QNAME);
assertEquals(svc2QN, svcQNParam2_redo.getValue());
// Read in the message contexts and activate them, which is required by message
// context deserialization to connect the message context to existing runtime
// objects such as AxisService
MessageContext mcRead1 = deserializeMessageContext(baos1);
ConfigurationContext configContext1 = endpointDesc1_redo.getServiceDescription().getAxisConfigContext();
assertNotNull(configContext1);
mcRead1.activate(configContext1);
AxisService asRead1 = mcRead1.getAxisService();
assertNotNull(asRead1);
assertEquals(axisService1_redo.getName(), asRead1.getName());
assertSame(axisService1_redo, asRead1);
AxisServiceGroup agRead1 = mcRead1.getAxisServiceGroup();
assertNotNull(agRead1);
// Do the same for the second Message Context
MessageContext mcRead2 = deserializeMessageContext(baos2);
ConfigurationContext configContext2 = endpointDesc2_redo.getServiceDescription().getAxisConfigContext();
assertNotNull(configContext2);
assertSame(configContext1, configContext2);
mcRead2.activate(configContext2);
AxisService asRead2 = mcRead2.getAxisService();
assertNotNull("AxisService was not activated", asRead2);
assertEquals(axisService2_redo.getName(), asRead2.getName());
assertSame(axisService2_redo, asRead2);
AxisServiceGroup agRead2 = mcRead2.getAxisServiceGroup();
assertNotNull("AxisServiceGroup was not activated", agRead2);
// These keep the ports from being GC'd before the test method completes and
// freeing up the AxisServices
assertNotNull(port1);
assertNotNull(port2);
assertNotNull(port1_redo);
assertNotNull(port2_redo);
} catch (Exception t) {
t.printStackTrace();
fail("Caught throwable " + t);
} finally {
ClientMetadataTest.restoreOriginalFactory();
}
}
/**
* Deserialize a message context from the stream. IMPORTANT NOTE! After the
* message context is deserialized, the activate(...) method must be called on it.
* @param baos
* @return
* @throws IOException
* @throws ClassNotFoundException
*/
private MessageContext deserializeMessageContext(ByteArrayOutputStream baos)
throws IOException, ClassNotFoundException {
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bais);
MessageContext mcRead = new MessageContext();
mcRead.readExternal(ois);
return mcRead;
}
private ByteArrayOutputStream serializeMessageContext(MessageContext msgCtx)
throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
msgCtx.writeExternal(oos);
oos.flush();
oos.close();
return baos;
}
}