views:

1792

answers:

2

Is it possible to create a web service operation using primitive or basic Java types when using the Jaxb2Marschaller in spring-ws? For example a method looking like this:

@Override
@PayloadRoot(localPart = "AddTaskRequest", namespace = "http://example.com/examplews/")
public long addTask(final Task task) throws AddTaskFault {
 // do something
 return 0;
}

I am using the maven jaxws plugin to generate the interface and model classes from my WSDL. When I try to call the webservice I get the following error:

java.lang.IllegalStateException: No adapter for endpoint [...]: Does your endpoint implement a supported interface like MessageHandler or PayloadEndpoint

I found out that if I change the method to that:

@Override
@PayloadRoot(localPart = "AddTaskRequest", namespace = "http://example.com/examplews/")
public JAXBElement<Long> addTask(final JAXBElement<Task> task) throws AddTaskFault {
 final ObjectFactory objectFactory = new ObjectFactory();
 return objectFactory.createAddTaskResponse(0L);
}

I am able to call it - but this signature is not compatible with the interface generated by the maven jaxws plugin.

What can I do to configure either spring-ws to be able to use the first kind of implementation or to tell maven jaxws plugin to generate the second variant of the interface?

UPDATE: My relevant spring-ws config entries look like that:

<bean id="marshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
 <property name="contextPath" value="com.example.examplews" />
</bean>

<bean class="org.springframework.ws.server.endpoint.adapter.GenericMarshallingMethodEndpointAdapter">
 <constructor-arg ref="marshaller" />
</bean>

<bean class="org.springframework.ws.server.endpoint.mapping.PayloadRootAnnotationMethodEndpointMapping">
 <property name="order" value="1" />
</bean>
+4  A: 

When Spring-WS is trying to match an EndpointAdapter to an Endpoint, it checks that all of the parameters of the endpoint method, plus its return value, are types known to the Jaxb2Marshaller, and long will not. Conceptually, this makes sense, since JAXB would have no idea how to turn a long into XML without more information (which is where JAXBElement comes in).

You should realise that Spring-WS is not a JAX-WS implementation, and makes no pretense to be. You can't really expect to take JAX-WS-generated artifacts and expect them just to work in Spring_WS, although in many cases Spring-WS is flexible enough to deal with it.

skaffman
Ok, so what would be the best way to use spring ws with a top-down approach? I want to use maven to generate the necessary classes so that I just have to implement the web service interface.
Thomas Einwaller
I know of no generation tool that will do that, but then Spring-WS is very code-light, so you wouldn't really save that much typing.
skaffman
so you would recommend using bottom up and just write my code my web service interface?
Thomas Einwaller
Spring-WS advocates writing your XML schema first, then writing endpoints in java that receive and respond with documents conforming to that schema. The WSDL sort of falls naturally out of that process.
skaffman
A: 

Here is everything relevant in my config as I can't really tell what you could change, they are rather different and it has been a year and a half since i did this.

    <bean id="schemaCollection"
        class="org.springframework.xml.xsd.commons.CommonsXsdSchemaCollection">
        <property name="xsds" value="/my.xsd" />
        <property name="inline" value="true" />
    </bean>

    <bean id="marshallingEndpoint"
        class="....EndpointImpl">
    </bean>

    <oxm:jaxb2-marshaller id="marshaller" contextPath=".....schema" />

   <bean id="annotationMapping"      class="org.springframework.ws.server.endpoint.mapping.PayloadRootAnnotationMethodEndpointMapping">
        <property name="interceptors">
            <list>
                <bean class="org.springframework.ws.server.endpoint.interceptor.PayloadLoggingInterceptor" />
                <bean class="org.springframework.ws.soap.server.endpoint.interceptor.PayloadValidatingInterceptor">
                    <property name="xsdSchemaCollection"
                        ref="schemaCollection" />
                    <property name="validateRequest" value="true" />
                    <property name="validateResponse" value="true" />
                </bean>
            </list>
        </property>
        <property name="order" value="1" />
    </bean>

    <sws:marshalling-endpoints />

Hope it helps in some way. The Endpoint class had @Endpoint, the methods @PayloadRoot. They didn't return long, but I didn't have to wrap my class in the JAXBElement either.

[edit] namespaces

    xmlns:oxm="http://www.springframework.org/schema/oxm"
    xmlns:sws="http://www.springframework.org/schema/web-services"

    xsi:schemaLocation="
       http://www.springframework.org/schema/oxm 
       http://www.springframework.org/schema/oxm/spring-oxm-1.5.xsd"&gt;
laura
thanks, what namespaces are oxm and sws?
Thomas Einwaller