|
|
||
Jitendra Kotamraju's BlogFebruary 2007 ArchivesThread Scoped JAX-WS endpoint instancesPosted by jitu on February 09, 2007 at 05:44 PM | Permalink | Comments (0)This is similar to the other extension HttpSessionScope. Traditionally JAX-WS has never taken advantage of object state, just like servlet. That is, the container creates only one instance of your service class, and then have it serve all the requests concurrently. This makes it impossible to set values to instance fields, as you'll experience concurrency problem as soon as multiple threads hit your service. Say you have a service, and its web methods try to access Database using Connection object. Connection object doesn't handle concurrent accesses, hence the access needs to be synchronized. For e.g.: @WebService
public class DataService {
Connection con;
public synchronized void delete() {
Statement stmt = con.createStatement();
stmt.executeQuery();
}
public synchronized void add() {
Statement stmt = con.createStatement();
stmt.executeQuery();
}
}This will have performance issues since some of the requests need to wait until a current request is finished. To avoid synchronization, one could create Connection objects in each invocation and that is even more expensive! So we need exclusive access to Connection object and reuse them exclusively for other invocations. This can be achieved by creating more instances and using an instance exclusively for one invocation. To achive this, jax-ws runtime creates instances and stores and reuses them from ThreadLocal. import org.jvnet.jax_ws_commons.thread_scope.ThreadScope;
@WebService
@ThreadScope
public class DataService {
Connection con;
public void delete() {
Statement stmt = con.createStatement();
stmt.executeQuery();
}
public void add() {
Statement stmt = con.createStatement();
stmt.executeQuery();
}
}The @ThreadScope annotation tells the JAX-WS RI to create one instance of DataService per each thread. No need to have synchronized keyword. You can download the extension hereTubes in JAX-WS 2.1Posted by jitu on February 02, 2007 at 10:41 AM | Permalink | Comments (5)Few months back, Kohsuke mentioned about Tubes in his blog JAX-WS RI goes truly asynchronous! That time, it was working only in prototypes. Now JAX-WS 2.1 runtimes completely works on Tubes. The javadoc for Tube says, "Tube is a basic processing unit that represents SOAP-level protocol handling code. Multiple tubes are often put together in a line, and act on Packets in a sequential fashion". We converted all the JAX-WS processing units to Tubes(for e.g: mustunderstand processing is done in MUTube, invocation of web sevice endpoints is done in InvokerTube etc). Most developers need not worry about creating Tubes but an advanced user or a middleware developer may care to do so. This is also a good alternative to writing Handlers while retaining the performance. But this approach is not portable as you would be using com.sun.xml.ws.api classes. Advantages of TubesThere are quite a few advantages in writing your own Tube for SOAP processing.
Sample Tube to add SOAP headersOK, say you need to add a custom header to all the SOAP response messages. To do this :
Writing a TubeUsually, a Tube implementation would extend from AbstractFilterTubeImpl since there will be a next Tube in the processing tubeline. If your Tube is the last one in the processing tube line, it would extend from AbstractTubeImpl. Extending from these base classes is better as they provide good implementations for many methods. The javadocs provide complete information on all these things.
public class CustomTube extends AbstractFilterTubeImpl {
protected CustomTube(Tube next) {
super(next);
}
protected CustomTube(AbstractFilterTubeImpl that, TubeCloner cloner) {
super(that, cloner);
}
public CustomTube copy(TubeCloner cloner) {
return new CustomTube(this, cloner);
}
public NextAction processResponse(Packet packet) {
Message message = packet.getMessage();
if (message == null) { // oneway
return super.processResponse(packet);
}
HeaderList headers = message.getHeaders();
QName adQName = new QName("test", "test");
headers.add(Headers.create(adQName, "Advertisement"));
return super.processResponse(packet);
}
}
In the above CustomTube code
Writing a TubelineAssemblerTo place our CustomTube in the tubeline, we need to write a TubelineAssembler. I pretty much copied from default assembler and added our tube in server's tubeline. This needs to be improved in our runtime so that tubeline assembly is simple and easy.
Writing a TubelineAssemblerFactoryNext, we need to create TubelineAssemblerFactory that knows how to create TubelineAssemblers.public class CustomTubelineAssemblerFactory extends TubelineAssemblerFactory {
JAX-WS runtime discovers TubelineAssemblerFactory using service finder mechanism. It looks for META-INF/services/com.sun.xml.ws.api.pipe.TubelineAssemblerFactory and loads the factory entry in that file. So we add com.jitu.CustomTubelineAssemblerFactory in the file META-INF/services/com.sun.xml.ws.api.pipe.TubelineAssemblerFactory CustomTube in actionLet us create a jar customtube.jar with all the above classes and META-INF/services entry. The entries would look like:META-INF/services/com.sun.xml.ws.api.pipe.TubelineAssemblerFactory If you put this jar in the classpath of the container, you would see there is an additional header in every SOAP response message ...You can download the source zip of the above code. In future, we will come up with an easier way to plug-in a Tube. | ||
|
|