Hi Mika,
I recently read thru your tutorial
(http://raibledesigns.com/wiki/AppFuseXFire.html) on Xfire for Appfuse
and I'd like to say, nice job! Although I'm not direclty using appfuse
in my current project I have in the past and have found to be
fantastic way to jump start my development activites.
But I digress, onto the real point of my message -- I've got
Xfire/Junit testing woes....
In a nutshell I'm tripping up over some Xfire gotchas and being very
new to this technology don't quite yet have enough experience to
bootstap myself up. Essentially, I've crafted this web service
called IEchoWebService (see ~~~ IEchoWebService ~~ below) along with a
JUnit test called EchoWebServiceTest (See ~~~~ EchoWebServiceTest ~~~~
below) that current contains two methods: 1) testGetWsdl(), and 2)
testEcho().
The testGetWsdl() I modelled directly after your example and it passes
without a hitch. In fact, I'm also have this test print out the WSDL
(See ~~~~WSDL ~~~~ below) for my web service and that looks fine too.
However, the second test, testEcho() seems to act like it can't
establish a connection with the service itself (Btw, I'm running this
test in the Eclipse Debugger). In fact, when I make either of the
"IEcho echoIn = service.createEcho();" or "IEcho echoOut =
service.echo(echoIn);" (See ~~~ Unit Test ~~~ below) calls I first
notice a very long delay followed typically by the message "Invalid
Stack Frame" printed in the "Variables" window but *NO* exceptions are
generated. After a period of time these calls return but the
corresponding IEcho objects I expect to get back end up being 'null'.
Looking at the logs (See ~~~~ Logs ~~~~) everything looks quite
reasonable there as well.
Needless to say, I've hunted and pecked around the Net looking for
information on this problem. I've examined quite closely your Appfuse
EchoWebServceTest & UserWebServiceTests, which btw work just fine, and
I'm stumpped. If you would be so kind to take a peek and shoot my
your thoughts I would truly appreciate the help.
Thanks much in advance,
John Daly
Hewlett-Packad
[EMAIL PROTECTED]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ IEchoWebService Interface
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
public interface IEchoWebService
{
/**
* Creates a blank object by calling Echo's constructor
*
* @return the new IEcho object
*/
public IEcho createEcho();
/**
* Creates a query object based on the inputted object and returns
that
* object
*
* @param echoQuery
* is the object that the query is based on
* @exception QueryException
* if the inputted object to base the query on was null
* @return the query object to be used for searches
*/
public IQuery createQuery(IEcho echoQuery);
/**
* Given a query object, the function searches the database for all
matching
* echos. Returns a single item if only one item matched or null if
nothing
* was found in the search.
*
* @param query
* object to be used to search the database
* @exception FindException
* only if the inputted query was null
* @return the object found or null if nothing was found
*/
public IEcho findEcho(IQuery query);
/**
* Returns an iterator that represents all the echos found
*
* @param query
* that the search is based on
* @exception FindException
* if the inputted query object is null
* @return the iterator that encompasses the found echos
* @return null if nothing is found
*
* Tell xfire, which objects it will find in the List
*
* @aegis.method
* @aegis.method-return-type
componentType="com.hp.ipgit.ssa.echoservice.model.IEcho"
*/
public List findEchos(final IQuery query);
/**
* Attempts to insert a given object into the database
*
* @param the
* IEcho to be inserted
* @exception InsertException
* if the given object was null, not valid, or a
duplicate
* of something already in the database
* @return the object that was inserted, now with an updated GUID
field
*/
public IEcho insertEcho(IEcho object);
/**
* Removes the given object from the database and all child nodes
* underneath it
*
* @param the
* object to be removed
* @exception RemoveException
* if the inputted object is null or not in the
database
* @return the object that was removed
*/
public IEcho removeEcho(IEcho object);
/**
* Updates the values of the given object in the database
*
* @param the
* object to be updated
* @exception UpdateException
* if the given object is null, not valid, or was
updated in
* a way that conflicts with other members of the
database
* @return the updated object
*/
public IEcho updateEcho(IEcho object);
/**
* This method tests the entire SSA Service stack by routing the
incoming
* echo message object throughout all the layers of the service stack
* including the database while attaching a short phrase before
returning
* it to the caller.
*
* The primary purpose of this method is to demonstrate that all each
* layer of this SSA Service is functioning properly.
*
* @param the IEcho object carrying the message to be echoed.
* @return the modified IEcho message.
*/
public IEcho echo(IEcho object);
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ WSDL
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:tns="http://xfire.remoting.echoservice.ssa.ipgit.hp.com"
xmlns:wsdlsoap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:ns1="http://query.model.ssa.ipgit.hp.com"
xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:ns2="http://model.echoservice.ssa.ipgit.hp.com"
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
targetNamespace="http://xfire.remoting.echoservice.ssa.ipgit.hp.com">
<wsdl:types>
<xsd:schema targetNamespace="http://query.model.ssa.ipgit.hp.com"
elementFormDefault="qualified" attributeFormDefault="qualified">
<xsd:complexType name="IQuery">
<xsd:sequence>
<xsd:element name="alias" type="xsd:string" nillable="true" />
<xsd:element name="query" type="ns1:IQuery" nillable="true" />
</xsd:sequence>
</xsd:complexType>
</xsd:schema>
<xsd:schema
targetNamespace="http://xfire.remoting.echoservice.ssa.ipgit.hp.com"
elementFormDefault="qualified" attributeFormDefault="qualified">
<xsd:element name="findEchos">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="in0" type="ns1:IQuery" minOccurs="1"
maxOccurs="1" />
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="findEchosResponse">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="out" type="ns2:ArrayOfIEcho"
minOccurs="1" maxOccurs="1" />
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="findEcho">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="in0" type="ns1:IQuery" minOccurs="1"
maxOccurs="1" />
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="findEchoResponse">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="out" type="ns2:IEcho" minOccurs="1"
maxOccurs="1" />
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="updateEcho">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="in0" type="ns2:IEcho" minOccurs="1"
maxOccurs="1" />
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="updateEchoResponse">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="out" type="ns2:IEcho" minOccurs="1"
maxOccurs="1" />
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="echo">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="in0" type="ns2:IEcho" minOccurs="1"
maxOccurs="1" />
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="echoResponse">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="out" type="ns2:IEcho" minOccurs="1"
maxOccurs="1" />
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="removeEcho">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="in0" type="ns2:IEcho" minOccurs="1"
maxOccurs="1" />
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="removeEchoResponse">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="out" type="ns2:IEcho" minOccurs="1"
maxOccurs="1" />
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="createEcho">
<xsd:complexType />
</xsd:element>
<xsd:element name="createEchoResponse">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="out" type="ns2:IEcho" minOccurs="1"
maxOccurs="1" />
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="createQuery">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="in0" type="ns2:IEcho" minOccurs="1"
maxOccurs="1" />
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="createQueryResponse">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="out" type="ns1:IQuery" minOccurs="1"
maxOccurs="1" />
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="insertEcho">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="in0" type="ns2:IEcho" minOccurs="1"
maxOccurs="1" />
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="insertEchoResponse">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="out" type="ns2:IEcho" minOccurs="1"
maxOccurs="1" />
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<xsd:schema
targetNamespace="http://model.echoservice.ssa.ipgit.hp.com"
elementFormDefault="qualified" attributeFormDefault="qualified">
<xsd:complexType name="ArrayOfIEcho">
<xsd:sequence>
<xsd:element name="IEcho" type="ns2:IEcho" nillable="true"
minOccurs="0" maxOccurs="unbounded" />
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="IEcho">
<xsd:sequence>
<xsd:element name="ID" type="xsd:string" nillable="true" />
<xsd:element name="message" type="xsd:string" nillable="true" />
</xsd:sequence>
</xsd:complexType>
</xsd:schema>
</wsdl:types>
<wsdl:message name="findEchoResponse">
<wsdl:part name="parameters" element="tns:findEchoResponse" />
</wsdl:message>
<wsdl:message name="echoRequest">
<wsdl:part name="parameters" element="tns:echo" />
</wsdl:message>
<wsdl:message name="updateEchoResponse">
<wsdl:part name="parameters" element="tns:updateEchoResponse" />
</wsdl:message>
<wsdl:message name="updateEchoRequest">
<wsdl:part name="parameters" element="tns:updateEcho" />
</wsdl:message>
<wsdl:message name="findEchosRequest">
<wsdl:part name="parameters" element="tns:findEchos" />
</wsdl:message>
<wsdl:message name="createEchoResponse">
<wsdl:part name="parameters" element="tns:createEchoResponse" />
</wsdl:message>
<wsdl:message name="echoResponse">
<wsdl:part name="parameters" element="tns:echoResponse" />
</wsdl:message>
<wsdl:message name="createQueryResponse">
<wsdl:part name="parameters" element="tns:createQueryResponse" />
</wsdl:message>
<wsdl:message name="findEchoRequest">
<wsdl:part name="parameters" element="tns:findEcho" />
</wsdl:message>
<wsdl:message name="removeEchoResponse">
<wsdl:part name="parameters" element="tns:removeEchoResponse" />
</wsdl:message>
<wsdl:message name="insertEchoResponse">
<wsdl:part name="parameters" element="tns:insertEchoResponse" />
</wsdl:message>
<wsdl:message name="removeEchoRequest">
<wsdl:part name="parameters" element="tns:removeEcho" />
</wsdl:message>
<wsdl:message name="createQueryRequest">
<wsdl:part name="parameters" element="tns:createQuery" />
</wsdl:message>
<wsdl:message name="findEchosResponse">
<wsdl:part name="parameters" element="tns:findEchosResponse" />
</wsdl:message>
<wsdl:message name="insertEchoRequest">
<wsdl:part name="parameters" element="tns:insertEcho" />
</wsdl:message>
<wsdl:message name="createEchoRequest">
<wsdl:part name="parameters" element="tns:createEcho" />
</wsdl:message>
<wsdl:portType name="IEchoWebServicePortType">
<wsdl:operation name="findEchos">
<wsdl:input name="findEchosRequest"
message="tns:findEchosRequest" />
<wsdl:output name="findEchosResponse"
message="tns:findEchosResponse" />
</wsdl:operation>
<wsdl:operation name="findEcho">
<wsdl:input name="findEchoRequest" message="tns:findEchoRequest" />
<wsdl:output name="findEchoResponse"
message="tns:findEchoResponse" />
</wsdl:operation>
<wsdl:operation name="updateEcho">
<wsdl:input name="updateEchoRequest"
message="tns:updateEchoRequest" />
<wsdl:output name="updateEchoResponse"
message="tns:updateEchoResponse" />
</wsdl:operation>
<wsdl:operation name="echo">
<wsdl:input name="echoRequest" message="tns:echoRequest" />
<wsdl:output name="echoResponse" message="tns:echoResponse" />
</wsdl:operation>
<wsdl:operation name="removeEcho">
<wsdl:input name="removeEchoRequest"
message="tns:removeEchoRequest" />
<wsdl:output name="removeEchoResponse"
message="tns:removeEchoResponse" />
</wsdl:operation>
<wsdl:operation name="createEcho">
<wsdl:input name="createEchoRequest"
message="tns:createEchoRequest" />
<wsdl:output name="createEchoResponse"
message="tns:createEchoResponse" />
</wsdl:operation>
<wsdl:operation name="createQuery">
<wsdl:input name="createQueryRequest"
message="tns:createQueryRequest" />
<wsdl:output name="createQueryResponse"
message="tns:createQueryResponse" />
</wsdl:operation>
<wsdl:operation name="insertEcho">
<wsdl:input name="insertEchoRequest"
message="tns:insertEchoRequest" />
<wsdl:output name="insertEchoResponse"
message="tns:insertEchoResponse" />
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="IEchoWebServiceHttpBinding"
type="tns:IEchoWebServicePortType">
<wsdlsoap:binding style="document"
transport="http://schemas.xmlsoap.org/soap/http" />
<wsdl:operation name="findEchos">
<wsdlsoap:operation soapAction="" />
<wsdl:input name="findEchosRequest">
<wsdlsoap:body use="literal" />
</wsdl:input>
<wsdl:output name="findEchosResponse">
<wsdlsoap:body use="literal" />
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="findEcho">
<wsdlsoap:operation soapAction="" />
<wsdl:input name="findEchoRequest">
<wsdlsoap:body use="literal" />
</wsdl:input>
<wsdl:output name="findEchoResponse">
<wsdlsoap:body use="literal" />
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="updateEcho">
<wsdlsoap:operation soapAction="" />
<wsdl:input name="updateEchoRequest">
<wsdlsoap:body use="literal" />
</wsdl:input>
<wsdl:output name="updateEchoResponse">
<wsdlsoap:body use="literal" />
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="echo">
<wsdlsoap:operation soapAction="" />
<wsdl:input name="echoRequest">
<wsdlsoap:body use="literal" />
</wsdl:input>
<wsdl:output name="echoResponse">
<wsdlsoap:body use="literal" />
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="removeEcho">
<wsdlsoap:operation soapAction="" />
<wsdl:input name="removeEchoRequest">
<wsdlsoap:body use="literal" />
</wsdl:input>
<wsdl:output name="removeEchoResponse">
<wsdlsoap:body use="literal" />
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="createEcho">
<wsdlsoap:operation soapAction="" />
<wsdl:input name="createEchoRequest">
<wsdlsoap:body use="literal" />
</wsdl:input>
<wsdl:output name="createEchoResponse">
<wsdlsoap:body use="literal" />
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="createQuery">
<wsdlsoap:operation soapAction="" />
<wsdl:input name="createQueryRequest">
<wsdlsoap:body use="literal" />
</wsdl:input>
<wsdl:output name="createQueryResponse">
<wsdlsoap:body use="literal" />
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="insertEcho">
<wsdlsoap:operation soapAction="" />
<wsdl:input name="insertEchoRequest">
<wsdlsoap:body use="literal" />
</wsdl:input>
<wsdl:output name="insertEchoResponse">
<wsdlsoap:body use="literal" />
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="IEchoWebService">
<wsdl:port name="IEchoWebServiceHttpPort"
binding="tns:IEchoWebServiceHttpBinding">
<wsdlsoap:address
location="http://localhost/services/IEchoWebService" />
</wsdl:port>
</wsdl:service>
</wsdl:definitions>
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ UNIT TEST
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
public class EchoWebServiceTest extends AbstractXFireSpringTest
{
protected final Log _log = LogFactory.getLog(getClass());
public void setUp() throws Exception
{
super.setUp();
}
public void testGetWsdl() throws Exception
{
Document doc = getWSDLDocument("IEchoWebService");
printNode(doc);
assertValid("//xsd:[EMAIL PROTECTED]"findEcho\"]", doc);
assertValid("//xsd:[EMAIL PROTECTED]"findEchoResponse\"]", doc);
}
public void testEcho() throws Exception
{
XFireProxyFactory factory = new XFireProxyFactory(getXFire());
IEchoWebService service = (IEchoWebService)
factory.create(getServiceRegistry().getService("IEchoWebService"),"xfire.local://IEchoWebService");
IEcho echoIn = service.createEcho();
echoIn.setMessage("A test echo message");
IEcho echoOut = service.echo(echoIn);
assertNotNull(echoOut);
assertEquals(echoOut.getMessage(), "EchoService
:"+echoIn.getMessage());
}
protected ApplicationContext createContext()
{
String ssaPkg =
ClassUtils.classPackageAsResourcePath(GlobalConstants.class);
String[] paths = { "classpath*:/" + ssaPkg +
"/**/*applicationContext*.xml" };
return new ClassPathXmlApplicationContext(paths);
}
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~Logs
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[ssa:ssa] INFO [main] DriverManagerDataSource.setDriverClassName(155)
| Loaded JDBC driver: org.postgresql.Driver
[ssa:ssa] INFO [main] LocalSessionFactoryBean.afterPropertiesSet(724)
| Building new Hibernate SessionFactory
[ssa:ssa] DEBUG [main] DefaultTransportManager.register(107) |
Registered transport
[EMAIL PROTECTED]
[ssa:ssa] DEBUG [main] DefaultTransportManager.register(107) |
Registered transport
[EMAIL PROTECTED]
[ssa:ssa] DEBUG [main] DefaultTransportManager.register(107) |
Registered transport
[EMAIL PROTECTED]
[ssa:ssa] DEBUG [main] DefaultTransportManager.register(107) |
Registered transport
[EMAIL PROTECTED]
[ssa:ssa] INFO [main] ServiceBean.afterPropertiesSet(137) | Exposing
SOAP v.1.1 service with name IEchoWebService
[ssa:ssa] DEBUG [main] DefaultTransportManager.register(107) |
Registered transport
[EMAIL PROTECTED]
[ssa:ssa] DEBUG [main] DefaultTransportManager.register(107) |
Registered transport
[EMAIL PROTECTED]
[ssa:ssa] DEBUG [main] DefaultTransportManager.register(107) |
Registered transport
[EMAIL PROTECTED]
[ssa:ssa] DEBUG [main] DefaultTransportManager.register(107) |
Registered transport
[EMAIL PROTECTED]
[ssa:ssa] DEBUG [main] XFireProxy.invoke(50) | Method [createEcho]
[ssa:ssa] DEBUG [main] LocalTransport.createNewChannel(38) | Creating
new channel for uri: xfire.local://114539853332302117152915
[ssa:ssa] DEBUG [main] HandlerPipeline.invoke(95) | Invoking handler
org.codehaus.xfire.soap.handler.SoapSerializerHandler in phase transport
[ssa:ssa] DEBUG [main] HandlerPipeline.invoke(95) | Invoking handler
org.codehaus.xfire.soap.handler.SoapActionOutHandler in phase transport
[ssa:ssa] DEBUG [main] HandlerPipeline.invoke(95) | Invoking handler
org.codehaus.xfire.handler.OutMessageSender in phase send
[ssa:ssa] DEBUG [main] LocalTransport.createNewChannel(38) | Creating
new channel for uri: xfire.local://IEchoWebService
[ssa:ssa] DEBUG [Thread-1] DefaultEndpoint.onReceive(34) | Received
message to xfire.local://IEchoWebService
[ssa:ssa] DEBUG [main] XFireProxy.invoke(61) | Result [null]