Monday, November 3, 2008

EJB 3.0 and Web Services in WebSphere App Server v7.0

One of the questions I get most frequently on the EJB 3.0 feature pack for WebSphere App Server 6.1, is where a customer has installed both the EJB 3.0 feature pack and the Web Services feature pack, and wants to expose their EJB 3.0 bean as a JAX-WS web service endpoint, like so:

@WebService

@Stateless

public class MyEJB3WebServiceBean implements MyCoolService {

...

}


Unfortunately, we weren't able to directly support this scenario via the v6.1 feature packs, since doing so would have required that each feature pack depend on function in the other feature pack -- something that wasn't allowed in the overall definition for the v6.1 feature packs. We published a workaround for this, where you use a "helper class" as the JAX-WS implementation and have that class just forward the incoming requests to the target EJB 3.0 bean. It works just fine, but is nowhere near as nice as just having a single class that's both the endpoint definition and implementation.

The good news is that with WebSphere App Server v7.0, you can directly annotate your EJB 3.0 beans with the @WebService or @WebMethod annotation (just like the code above) and have them directly accessible via a JAX-WS endpoint; no "helper" class required. The Rational Application Developer (RAD) 7.5 tooling also makes it easy to code up your EJB 3.0 beans this way.

The ease-of-use combination of EJB 3.0 and JAX-WS is really, really nice. WebSphere App Server v7.0 makes it easy to implement this powerful combination of function.

12 comments:

Anonymous said...

Is it possible to use JAX-WS and Soap over JMS with websphere 6.1 using some kind of a similar "workaround"?

Also, could you point to the URL where the workaround you mentioned is described?

Thanks.

Randy Schnier said...

Hi, thanks for your comment/question.

The workaround can be employed to forward incoming JAX-WS requests to any outgoing protocol or location that you wish. It really depends on what Java code you place in the methods of the JAX-WS object that's performing the translation/forwarding function. In the case of the EJB 3.0 forwarder, the JAX-WS object obtains a reference to the target EJB 3.0 bean/interface, and invokes the same-named method on the EJB interface. It then takes any return argument coming back from the EJB invocation and passes that back as the result of the JAX-WS invocation.

The workaround is described in the IBM Redbook: WebSphere Application Server 6.1 Feature Pack for EJB 3.0, available for download at http://www.redbooks.ibm.com/abstracts/sg247611.html . Hope this helps.

- Randy

Greg Truty said...

To augment to Randy's comment, if you meant can you use SOAP/JMS (as an inbound protocol) and dispatch to a JAX-WS implementation bean, the answer is no in the Feature Pack for Web Services. For that, you will have to migrate up to WebSphere v7.0.

Anonymous said...

Have you tried this with RAD 7.5 Websphere 7.0? Any examples anywhere?

I have not been able to get this working. I can annotate with @WebService and publishing does create helper classes. But how does one expose this endpoint through http without any WAR?

Greg Truty said...

anonymous,
If you look at the documentation (see here: http://publib.boulder.ibm.com/infocenter/wasinfo/v7r0/index.jsp?topic=/com.ibm.websphere.web20fep.multiplatform.doc/info/ae/ae/twbs_devwbsjaxws.html

you will see that endptEnabler is required to be run. That will add the WAR file. Why we continue to use endptEnabler is a little bit of legacy, but it's also to help with using transport level security to secure the bean (and not use new metadata). Over time (i.e. future releases), we have the requirement to remove the router war. Hope this helps explain the rationale.

Anonymous said...

Greg Truty,

Thank you for that. I am aware of using the enpoint enabler, and the generation of the Router war. I think what I should be saying is that I already have a war, and was wondering if it is possible to expose the EJB through this WAR in an automated (RAD tool generated) way. Even if it is command line tool.
Could you please explain what you mean with "the requirement to remove the router war"? How will this be achieved, in other words how will the endpoint be exposed without a war?
I ask these questions cause it will influence decisions I need to make now.

Greg Truty said...

IBM cannot speak about future works publicly, however the general idea being considered is to register internally with our web container or HTTP channel and not expose a WAR directly. In doing so though, that means that any metadata/capabilities that customers would do in that router war (say security) would need to have it's metadata specified for said capabilities in a new fashion.

Henk said...

greg truty,

Thank you. That helps a lot.

Maybe you can give me some more insight into the advantages of using the endptenabler. You mentioned not using new metadata for security. Could you be more specific as to what metadata you are refering to, or perhaps some example.

As I see it at the moment the advantages of using the endptenabler are the following.
1. All code are generated, no need for re-doing any boilerplate coding to do the ejb calls from the war.
2. Re-use of the meta data, but I am not sure if I understand this. From my understanding just having a war gives you that, or am I missing something here?

The disadvantage in my context is that this code generation can not be done into one of my own already defined wars. I have to use the created router war.

If I have any further questions around JAX-WS, where will be the best place to ask them?

Greg Truty said...

It's not so much an "advantage" to use endptenabler, as it's a required function part of the "deployment" process for WebSphere.

I understand the desire to use the same WAR, however there really isn't that much difference (in WebSphere) in deploying a single war versus two wars in an application. The WARs can even share parts of the same context root (so, that information doesn't even have to be exposed externally). e.g. war1 has a context root of /henk and war2 has a context root of /henk/services

As to the type of metadata I'm talking about, it's pure web.xml sort of metadata. For example, taking a JAX-WS bean and running endptEnabler on it, you will see that we generate in the router module are essentially the "servlet" definitions which use/define a base IBM web services class - as well as URI patterns pointing to said servlets.

Now, Security constraints can be added.

I'm finding the "blog" comment forum not the optimal place to get into examples, so if you want to talk more (and ask some questions on JAX-WS), send me an email (my email address is in my profile).

Sal said...

I'm trying to use the endptEnabler (WAS 7.0.0.7) but it just ends up "corrupting" the ear. Deploying the ear from the admin console gives a SAXParseException: Premature End of file. Any ideas on why this is happening and if there is a fix pack available?

Henry Chung said...

Hi Sal, we would need more information to understand what is the problem. Could you get a PMR open? And we can work through the PMR channel.

Sal said...

Thanks for your reply. I was able to resolve the issue. It turns out that I have to give a new/different context root from the one in which my Web Service class is deployed while running the endptEnabler. I was just accepting the default given by the tool, which is the context root for my web app hosting the web service class. I think the tool showing an incorrect default is misleading. In addition, the message while deploying was very misleading and not helpful in troubleshooting the issue.