Skip to main content

Alternative to JAX-WS RI's wsgen

Posted by jitu on March 3, 2008 at 3:13 PM PST


Wrapper Beans

See a simple doc/lit wrapper style web service starting from java.

package pkg;

import javax.jws.WebService;
import javax.jws.WebMethod;
import javax.xml.ws.Endpoint;

@WebService
public class AddService {
    @WebMethod(exclude=true)
    public static void main(String ... args) throws Exception {
        Endpoint.publish("http://localhost:8181/add", new AddService());
        ...
    }

    public int add(int num1, int num2) {
        return num1+num2;
    }
}

$ javac pkg/AddService.java
$ wsgen.sh -d gen -keep -cp . pkg.AddService
$ ls gen/pkg/jaxws
Add.class AddResponse.class

Here Add.class and AddResponse.class are request and response wrapper bean classes respectively.

So far with JAX-WS RI, you need to run wsgen for doc/lit wrapper case or when service throws any checked exceptions. wsgen generates request/response wrapper bean classes and exception bean classes. JAX-WS spec clearly defined rules to create these portable classes, so that the same application works on different JAX-WS implementations. But all the required information to generate these classes can be got from the SEI, so an implementation may generate these classes on the fly. From JAX-WS RI 2.1.4 onwards, you don't have to run wsgen, the runtime takes care of it by generating these classes dynamically. That's right, you don't have to run "wsgen" ! See the sample logging output, when there are no wrapper classes in the classpath:

$ javac pkg/AddService.java
$java pkg.AddService

INFO: Dynamically creating request wrapper Class pkg.jaxws.Add
Mar 3, 2008 1:58:30 PM com.sun.xml.ws.model.WrapperBeanGenerator createBeanImage
INFO:
@XmlRootElement(name=add, namespace=http://pkg/)
@XmlType(name=add, namespace=http://pkg/, propOrder={arg0, arg1})
public class pkg.jaxws.Add {

    @XmlRootElement(name=arg0, namespace=)
    public I arg0

    @XmlRootElement(name=arg1, namespace=)
    public I arg1

}

INFO: Dynamically creating response wrapper bean Class pkg.jaxws.AddResponse
Mar 3, 2008 1:58:30 PM com.sun.xml.ws.model.WrapperBeanGenerator createBeanImage
INFO:
@XmlRootElement(name=addResponse, namespace=http://pkg/)
@XmlType(name=addResponse, namespace=http://pkg/)
public class pkg.jaxws.AddResponse {

    @XmlRootElement(name=return, namespace=)
    public I _return

}

I would say starting from java, building services have never been so easy :-) Let me know your feedback, you need to try the 2.1.x nightlies for this feature.

Comments

You might want to post a description blurb to be more palatable on the main page

One can use HelloWorld helloWorld = new HelloService().getHelloWorldPort(). Even this requires to generate the artifacts like HelloWorld ahead of the client compilation.

But I am not talking about client generation. I am talking about creating a web service with dynamic proxies. For more info, see my post on the Web Service endpoints in Mustang post (from January 2006 archives).

The client process for me is pretty much good because I think clients should all start from WSDL anyway (we never know if the client will even be implemented in Java).

-- Doug

Great!
This is an important step towards the ability to create dynamic proxy-based Web Service implementations that leave all WS-related annotations to the interface.
The part that is still missing is the ability to generate java.lang.reflect.Proxy classes with annotations. With that, creating a WS at runtime would be as easy as creating a proxy with @WebService(serviceEndpointInterface=...) and handling web services calls through an InvocationHandler.

Hi, this is a little bit incompatible with WSGen: - WSGen generated request/response wrappers for all methods marked with @WebMethod - With dynamic creation, request/response wrappers are generated for all methods except for those marked with excluded=true. You should definitely not generate req/resp wrappers for methods that are not marked with @WebMethod.

See the web method calculation in https://jax-ws.dev.java.net/issues/show_bug.cgi?id=577

Whats the ETA to have this working out of the box in netbeans ?.

It looks like the client is just as simple to setup using an interface. Although it would be nice to have a factory pull out the qualified names from the WSDL, but that shouldn't be too terribly difficult to put together. URL wsdl = new URL("http://localhost:8080/sep-metro-engine/helloworld?WSDL"); Service service = Service.create(wsdl, new QName("http://metro.atlatl.com/", "HelloWorldImplService")); HelloWorld helloworld = (HelloWorld)service.getPort(HelloWorld.class); String message = helloworld.getHelloWorld("Test"); System.out.println(message);

This is great. I hate generating artifacts. The only thing keeping me from using the reference implementation now is the client call. Any examples regarding the client would be appreciated.

well, I don't see the big deal to generate or not the artifacts for SOA. Actually, it seems more a desperate attempt to satisfy the script mania (paranoia?) than something with impact in quality of serious systems.

I am working with SOA for more than six months now, and most part of the problem goes far beyond the mechanism to publish the web-services. Validation, security, transaction and several other details are more complicated - and won't be more or less difficult if you need to press a button or two. As early adopter of WSIT, I continue to see the WSDL and its details as the biggest problem. It is difficult to master WSDL definition and the business scenario is not always easy to model. To avoid WSDL edition and try to create Java classes instead, or groovy script or Spring pojos, or any other strategy to escape from WSDL seems not effective. At the end, the main issue continue to be the design of the system, and there is no script or trick that can help :)

Hi Felipe. Do you have specific suggestions for either Jitu, the OpenESB, or another group in the GlassFish community, that would help you in your tasks? If so, drop me an email at pelegri at sun dot com. Thanks - eduard/o