|
|
 |
Integrating Apache SOAP with an EJB Server
By Billy Newport, EJB Consultant.
Part 1 |
Part 2 |
Part 3 |
Part 4
This is part two of using Apache SOAP V2.0 with a J2EE server. Click this for Part 1 of SOAP.
Issues with the HTTP implementation provided with Apache SOAP.
There are some issues you need to be aware of when using Apache SOAP V2.0.
If you look at the source code for org.apache.soap.util.net.HTTPUtils then you'll see that
they are simply using a Socket to do the HTTP connection. This results in the following consequences:
- No Proxy/Socks support.
If you need to use a http proxy or socks server to reach the server then it won't work. They assume your client
can directly open a socket to the server.
- HTTP Security support.
They haven't implemented this aspect of the HTTP protocol. The SOAPHTTPConnection class could be modified to detect the
401 response and retry the RPC once the user name and password have been provided.
- HTTP/SSL support with certificate based authentication.
This is missing. They only support standard HTTP, no SSL.
- No cookie support.
If you are planning on making use of the HTTPSession on the servlet side then you're out of luck. The SOAP client doesn't
send any cookies to the server so the session tracking won't work. This is a performance problem with WAS as with out cookie
support, the client will be forced to authenticate with WAS on every request. This is a significant overhead. We need cookie
support so that the LPTA cookie is sent to the server on subsequent requests.
- It opens a new socket for every RPC.
This will cause you performance problems. If you are sending a lot of RPCs between the client and the server then keeping
the socket open is significantly faster then opening a new one on each request.
So, I think it's fair to say that for all but the most basic of applications, you will need to provide your own HTTP
transport implementation until the Apache one comes up to speed. It is not suitable for use in applets right now unless
you provide your own HTTP connection implementation that is at least HTTP proxy aware.
Rather than writing your own HTTP protocol handler, you can download one from the following site,
Innovation HttpClient.
This provides an applet/application compatible HTTP client only library that works with socks and HTTP proxy servers. The site also
provides some very useful information on HTTP in general. It also gives links to common SSL implementations and provides
patches to make these work with HTTPClient. I'll be using HttpClient for my HTTP connections in this series. I will also
be using the Sun JSSE SSL library to implement SSL and Certificate based authentication with WebSphere. We'll cover basic authentication
in this article and SSL and certificate authentication will be covered in the next article. You need a patch from
Innovation for it to work properly with JSSE. This is available on their site. Installing the patch is straight
forward. I just imported their 0.3-2 client, imported JSSE and then imported their patch on top.
Writing our own HTTP SOAP transport.
We're going to use our own HTTP transport because of the problems above. I downloaded the 0.3-2 HTTP client from the
innovation web site and loaded it in to Visual Age in its own project. I had no issues with it during this process, all
went smoothly. The next problem is to provide a new SOAP transport for our client. Apache SOAP is very well written IMHO and makes
this task very easy. I wrote a new class that implements the SOAPTransport interface. The class basically provides the following
functionality:
- Send a HTTP request to the server.
- A method to get the response to the above request.
- A method to get the headers returned in the response to the above request.
I wrote this class and implemented the above methods using the HTTPClient library. This is simple
and required less than a 100 lines of Java code. Click here for the HTTP Transport source. The send method
basically acts as an adapter method between the data structures Apache SOAP uses (HashTables) for headers and the ones
HTTPClient uses (NVPair arrays).
It's important to realize that this is only needed for the client. The server uses WebSpheres servlet engine and this provides
all the HTTP and HTTP/SSL support required for the servers operation.
So, now that we have a new SOAPTransport class, we need to modify the client to use it. The Call Object that the
client uses to send a SOAP request has a setSOAPTransport method. We simply invoke this method and supply it with
an instance of our SOAPTransport class. Here is the line to add:
call.setSOAPTransport(
new com.ejbinfo.soap.transport.http.SOAPHTTPConnection());
Add this line following where the Call object is constructed.
We also
invokes some initialization methods on the HTTPClient library to make it automatically accept cookies. If we don't do this
then it displays a dialog asking if the user wants to accept cookies. This is a SOAP client so the answer is always yes.
At this point, we're ready to test it all again, so we simply run the client. Everything should work as before and we see
the same address after we run the client in the client console.
Basic authentication.
We now want to enable security. We can't use the VAJ WTE to test this as it does not support security (please fix this if some
one from IBM is reading!). We will now deploy the application to a WAS 3.5.2 server. I've supplied an XML Config dump to help you
with this setup (it's below). But if you want to do it manually, I followed these steps:
- Create a new Application Server.
I used V3.5 compatibility mode. I don't see much point in the V2.2/JSP 1.1 mode until
VAJ also supports this.
- Make a new servlet engine and create a web application inside it.
- Add the file servlet.
- Add the rpc router servlet.
Use the same class as before. See my xmlconfig file for URL etc to use.
- Create the webapp directory with the servlet and web directories.
- Set the working directory to the default_host/xxx directory.
The SOAP dispatcher looks in the current directory
for the services store file. This is the working directory of the web application.
- Copy the soap directory from your VAJ WTE to the web directory in WAS.
So, you should have default_host/xxx/web/soap after this
step.
- Copy the ServicesStore file from the VAJ directory to the default_host/xxx directory.
This avoids the need
to redeploy the services.
- Modify the server command line arguments and add a -classpath to add the xerces.jar file.
This is not on the classpath
by default so we need to add it. Be sure to use the xerces.jar that is present in the appserver/lib directory.
- Copy the required jars to the servlet directory for the web app.
My servlets had the following jars.
- The patched SOAP runtime
- My HTTP transport classes
- The SOAP samples jar
- JSSE
- HTTPClient jars
Remember, we get the xerces jars from the websphere/appserver/lib directory. You must use the
xalan/xerces jars that comes with WAS. Also, remember to use the patched SOAP jars exported from VAJ and the
patched HTTPClient runtime (for JSSE support).
Some points to remember regarding the jars and WAS. Make sure the jars file extensions are in lower case,
i.e. .jar. WAS will ignore jars that have an upper case JAR extension. You don't specify each
JAR file individually on the web application class path. You need only specify the directory that contains
the JAR files. Turn off the auto reload feature. It's just going to slow everything down.
You should be ready to go now. Enter the URL for the soap directory and verify that the service is still deployed. If it
is not then you've copied the services store file to the wrong directory, incorrectly specified the working directory or used
an older version of the file that doesn't have our service deployed.
Now modify the command line parameters for our test
client in VAJ. Specify the URL that you mapped to the rpcrouter servlet above. My URL was
http://p300/soap/soap/servlet/rpcrouter. Run the client and it should work as before.
Basic security support (no SSL)
Next, enable security in WAS. I performed the following steps to do this:
- Create an Enterprise application.
- Create a method group called 'canSOAP'.
- Add the SOAP web application to this enterprise application.
- Add an ACL to the rpcrouter URL that limits access to the canSOAP method group.
- Add a user to the 'canSOAP' method group.
You can find a XmlConfig dump of my server here. You can use this (after editing it for your environment)
with the XMLConfig utility to quickly do all the above steps. I've dumped the server, deleted it and then imported it
from the XML file successfully. It recovers the enterprise application and the ACLs etc. You need to specify a substitution variable
on the command line to XMLConfig for the password. I'm using a Windows 2000 machine for this
article so you'll need to change host names (p300) and the user names (Administrator) for the correct
values in your environment.
Now, start the enterprise application and start the server holding the web application. Try to access the URL for the rpcrouter
using a browser. You should get prompted for a password. Remember the realm name on this dialog. It should be the same
as the realm for your enterprise application.
Our new HTTP transport understands cookies. It's default behaviour is to prompt you to know whether to accept cookies or not. Add
the following line to the main method of the client to automatically accept all cookies:
HTTPClient.CookieModule.setCookiePolicyHandler(null);
Run the client now. The client now uses the new HTTP transport. It understands the 401 HTTP response indicating that authentication
is required. You should see a dialog box appear prompting you for a user name and password. Supply the correct credentials and
the client should work. This shows the new transport is doing its job. Now, we'll look at how to programatically login with
the client.
Add the following line to the main method of the GetAddress sample:
HTTPClient.AuthorizationInfo.
addBasicAuthorization("p300",80,"EJBINFO","uid","pwd");
This tells the transport than when sending requests to the host p300 at port 80, if an authentication request for the realm EJBINFO
is received then supply uid and pwd as the password. So, your should specify the correct values for the above parameters
in your client, the above values won't work with out changes, you need to provide the correct values. Now run the client again
and it should not prompt you for the password this
time. The client automatically sends the correct credentials. Your client could prompt the user for these and
then supply them to the HTTP transport in a real application.
Basically, you need a line like the above for every server/realm combination your client
will connect to. The HTTP runtime figures out which credentials to use based on the host/port/realm key. The HTTP runtime also
supports cookies remember. This means that the LPTA cookies WAS sends will be handled correctly so we only login once for the session.
This is important as login is an expensive operation in WAS (mainly due to the LDAP look up).
Summary so far
So, we've come some way now. Let's enumerate what we've done so far. We modified Apache SOAP to work with a servlet V2.1 engine. We
made it work in the VAJ WTE to give us a development environment.
We tested it with the basic client. We updated the client to use our HTTP transport based on the innovation HTTPClient runtime and JSSE
from Sun. This lets our client support basic security, SSL, proxy servers, socks servers, persistent HTTP sessions, cookies
and certificate authentication. This is a significant improvement over the basic HTTP transport than Apache SOAP arrived with.
We deployed the server to WAS 3.5.2, enabled security and verified that the client stills
works and is responding to the authentication challenge successfully.
In the next article, we're write a SOAP service that talks to a session bean, we're going to do SSL and certificate based authentication. We've cover any gotchas for enabling SSL with WAS and
the certificate management. We'll do this with two clients. One simply uses basic authentication and HTTP/SSL as the transport
and the other uses HTTP/SSL with certificate based authentication.
Finally in the last article, we will show a MQ and JMS transport for SOAP.
|