I'm studying Jax-WS specification in general and its implementation on Glassfish 3.1.2. I built a simple standard example where a jax-ws soap based web service is called from a jsp page by using the artifacts generated through wsimport (the webservice and the jsp page are both deployed on Glassfish in the same EAR but in 2 different wars).
Everything works as expected but I have a question: looking at the application log, it seems that Glassfish creates a new instance of the webservice each time it is called. I would like to know where Java offically defines how a web container should manage webservice instances and if developers can customize this behaviour.
I read jax-ws 2.1 specification here
http://download.oracle.com/otndocs/jcp/jaxws-2.1-mrel2-eval-oth-JSpec/
but I found only a clue when speaking about how to publish a webservice using the Endpoint class by hand (section 5.2.2 "Publishing", page 69):
"An endpoint consists of an object that acts as the Web service implementation (called here implementor) plus some configuration information...
An Endpoint will be typically invoked to serve concurrent requests, so its implementor should be written so as to support multiple threads. The synchronized keyword may be used as usual to control access to critical sections of code. For finer control over the threads used to dispatch incoming requests, an application can directly set the executor to be used..."
This note is present even in Jax-WS 2.2 specification (used by Glassfish 3).
Actually, if I build a webservice using only JavaSE 7 (which includes Jax-WS 2.2), this description is true because there is only one instance of the webservice. Is there any reason why JavaEE doesn't follow this policy?
Thanks a lot for your help,
Nico
I found the answers on this specification (JSR-109):
http://jcp.org/aboutJava/communityprocess/mrel/jsr109/index3.html
It describes how Jax-WS works on JavaEE:
"4.1 Client Programming model (page 18)
a client must assume that the methods of a Web service have no state that is persistent across multiple Web service method invocations. A client can treat the Web service implementation as stateless.
The client has no control over the life cycle of the Web service implementation on the server. A client does not create or destroy instances of a Web service, which is referred to as a Port. The client only accesses the Port. The life cycle of the Ports, or instances of a Web service implementation, are managed by the run-time that hosts the Web service. A Port has no identity. This means that a client cannot compare a Port to other Ports to see if they are the same or identical, nor can a client access a specific Port instance.
5.3.2.4.2 Web container programming model for JAX-WS (page 42)
A Service Implementation must be a stateless object. A Service Implementation Bean must not save client specific state across method calls either within the bean instance’s data members or external to the instance. A container may use any bean instance to service a request.
5.3.4 Service Implementation Bean Life Cycle (page 43)
Before a request can be serviced, the container must instantiate a Service Implementation Bean and ready it for method requests.
A container may pool method ready instances of a Service Implementation Bean and dispatch a method request on any instance in a method ready state."
Moreover, the specification states that JavaEE must not use the Endpoint class to publish a webservice:
"5.3.3 Publishing Endpoints – javax.xml.ws.Endpoint (page 43)
JAX-WS provides functionality for creating and publishing Web Service endpoints dynamically using javax.xml.ws.Endpoint API. The use of this functionality is considered non-portable in a managed environment. It is required that both the Servlet and the EJB container disallow the publishing of the Endpoint dynamically, by not granting the publishEndpoint security permission."
Related
I have a simple question about deploying web services. Currently I have two endPoints, see below:
Endpoint.publish("http://localhost:8000/eCalcWS/eCalc", new eCalc());
Endpoint.publish("http://localhost:8001/eCalcWS/eCalc_service", new eCalc_service());
Is it possible to have two web services on the same address? How would I do that?
Unfortunately you can not the way you want.
The design is that each endpoint is associated with web service implementor.
From spec:
The Endpoint class can be used to create and publish Web service
endpoints. An endpoint consists of an object that acts as the Web
service implementation (called here implementor) plus some
configuration information, e.g. a Binding
and on publish (my emphasis):
publish(String address, Object implementor)
Creates and publishes an Endpoint for the given implementor. The binding is chosen by
default based on the URL scheme of the provided address (which must be
a URL). If a suitable binding if found, the endpoint is created then
published as if the Endpoint.publish(String address) method had been
called. The created Endpoint is then returned as the value of the
method.
I remember I also encounter this problem quite a while back which is really bad as I needed to associate 2-3 different implementations with different URLs and it was impossible (got address already bind error).
The way I got around this if I recall was to create my own dispatcher.
I published an endpoint that accepted web service requests for multiple endpoints and dispatched the request to the corresponding implementation. I worked directly on the SOAP message.
But it was possible for me since the xml messages were really simple and quite few.
For you I would recommend to publish in different endpoints if your web service implementations are non-trivial and have complicated messages and expect a lot of clients as the endpoint really just deploys a simple http server under the hood.
We have an application server that exposes a host of webservices. We are running a tomcat on the side that uses those webservices in JSF applications to provide a user interface. Suppose we have a bean that has a method "getWebservice()" that returns the proxy class used by jaxws to communicate with the webservice. This allows us to interact with the webservice with minimal effort: generate using wsimport, then use #{myBean.webservice.myProperty} etc
However as you can see this would require a lot of webservice interaction when reusing exposed methods. In our usecase most methods are rather static, at least for the duration of a #RequestScoped bean so the interaction of most methods should be cached once it is called (at least for one request).
Currently our setup is to create wrapper services in the bean and each wrapper does exactly the same thing:
if (methodResponse == null)
methodResponse = getWebservice().getMethod();
return methodResponse;
You can see that this gets very tiresome very quickly. Is there a way to annotate a jaxws method for caching? Or can I generate my own proxy class based on the interface and somehow "chain" it to the proxy used by jaxws (and perform generic caching) or can I create my own annotation that performs the caching?
You can create another caching Proxy around your web service client proxy object, and provide it with an InvocationHandler, that caches the result of method invocations.
Check out this blog post to see the complete step-by-step instruction and download sample code.
Webmethods Integration Server can integrate systems and orchestrate different web services from external systems on the network.
My question is: Is it possible to create Java code running in Webmethods Integration Server, and expose it as a web service? Therefore, having Webmethods host the web service.
yes that's possible. You can use a Java service inside IS to code your logic. You have to define an interface for this service (a doctype). After this is done, you create a webservice provider that calls your service.
This applies to IS from version 7 upwards.
Absolutely, that's one of the core purposes of the platform.
To expose any service (flow, java, adapter service etc) you need to create a web service connector (of type "Provider") and then drag the services you want to expose onto it. You can then point to the WSDL it generates.
The approach of webMethods to have everything as a service means that any code you write on the Integration Server can be added to one of these providers and thus invoked as a web service.
You can also proxy other web services (e.g. the wrap and layer approach) by building a web service connector (Provider) using an existing WSDL. What it will then do is mimic the existing WSDL and allow you to provide an implementation of it.
I have a client/server application that communicates via SOAP. The server-side application is a Java EE app that exposes web services using JAX-WS. I have a servlet filter setup to perform certain checks before a service is invoked.
This is all working pretty well, except for exception handling. If I throw an exception from the filter, it gets returned to the client as a generic server exception. I need to find a way to propagate a custom exception containing a specific message, so the client can display the message to the user.
Any insight?
A servlet filter isn't really the right tool if you want to send the exception in a SOAP response and I would consider using a JAX-WS handler for the verification of incoming messages instead (JAX-WS handlers are somehow to JAX-WS services what Filters are to Servlets).
Frmo Working with Headers in JAX-WS SOAPHandlers:
JAX-WS Handlers
In addition to support for web
services development, the JAX-WS
framework (the latest Java programming
language API for creating SOAP-based
web services and web service
consumers) also provides a handler
framework. Handlers provide a means
to inspect and manipulate incoming or
outgoing SOAP messages (on both the
client as well as server side). They
act as powerful message interceptors
that can perform an array of functions
such as message transformation,
content filtering, tracking, etc. In
fact, handlers are often used in
runtime environments to implement web
service and SOAP specifications such
as WS-Security, WS-ReliableMessaging,
etc. JAX-WS handlers are similar to
EJB interceptors or servlet filters.
Handlers, like interceptors and
filters, encourage developers to
follow the chain of responsibility
pattern.
Resources
Writing a Handler in JAX-WS (start here)
Handler example using JAXWS 2.0
References
Java API for XML-Based Web Services (JAX-WS) 2.0 specification
APIs
javax.xml.ws.handler.Handler
javax.xml.ws.handler.LogicalHandler
javax.xml.ws.handler.soap.SOAPHandler
Is there an elegant way to use Services across or between OSGi containers?
Is it even possible?
For instance, lets say I have a service interface on my local machine. What methodologies/technologies can I use to get that service interface accessible through a remote OSGi container's BundleContext?
There is a RFC called Remote Services (formerly Distributed OSGi) that does exactly what you are trying to achieve. The RFC is almost completed, and there are already 2 implementations provided respectively by Apache CXF and Eclipse ECF.
Both the implementations allows to do transparent remoting of an OSGi service. You just have to define the OSGi service as usual, and add some configuration parameters to make it a remote service.
Check:
http://cxf.apache.org/distributed-osgi.html
It is possible, but there are no libraries (afaik) that will do this for you. I've rolled my own for my current job. OSGi runtime on client and server, RMI is the transport. I've had to make HEAVY use of Proxy objects.
Register a service in the server's OSGi runtime (Equinox). I have a listener that watches all services looking for a property/attribute indicating this service should be exported (made remote), something like "remotable=true". It's easy to filter using the ServiceTracker. Over RMI I instruct the client to create a Proxy object with the service interface. All calls to this proxy object are generically send back over RMI (a call like execService serviceid, method name, var args params) and then invoked on the REAL service.
I've left out some of the low level details, but you can probably sort it out. If you can stray away from RMI, you may want to look into Riena (there may even be a way to write an RMI transport for Riena, I just haven't bothered to try)
It's not very clear what you are trying to achieve. You have got a service, you can access it using RMI, and you need to available as an OSGi service?
I guess you could write an interface to you local machine service. You could then write a bundle that connectes to that service and exposes that interface in the OSGi service registry. Then, your main bundle could locate that service using the interface name or service name.
It shouldn't be too much work to get an RMI connection to your local service. Maybe some config options to establish the initial connection. It might be important to write a facade for your service before you publish it in OSGi, in order to achieve some form of decoupling, and perhaps to hide the fact that it is an RMI service.
But then maybe I completely misunderstood you and all this is useless.
As well as CXF above, there's also Eclipse ECF, which is a collection of communication frameworks and provies an early implementation of the OSGi 4.2 remote services (aka distributed OSGi). It works by registering a local service to which your client binds in the VM, then creates a proxy on the remote machine, and using a technology of your choice (RMI, WebServices etc.) can remote the calls.
Obviously this uses by-value method invocation syntax (which your service needs to know about) but other than that, any comms errors are RuntimeException.
It certainly is possibly. Check out https://docs.paremus.com//display/NIM20/Home which includes an OSGi RSA implementation that includes a high performance RMI distribution provider.
Check the chapter "Remote Services" in the OSGi specification version 4.2.
It defines a standard way for distributing services between several OSGi containers.
The brand new version 4.3 of the OSGi spec has even more detailed support for this - see chapter 6 Remote Services and 112 Remote Service Admin Service.