Thursday, March 8, 2012

JBoss AS 7 - How to set the context root for an EJB3 WebService

Apologies to anyone who read one of my other blog posts and thought this one would be something interesting for anyone other than the very specific few who want this particular answer.  I tried to warn you with the title of the post.  For those of you who are reading because the JBoss Docs are, as ever, disorganized and littered with gaping holes, into which you are supposed to pour your guesses, past experience, head scratches, and frustrated, perplexed gazes, read on...

This is a simple answer that came from another week long session of searching, reading between the lines of the many attempts to document JBoss 7, and a little bit of guessing.  This particular topic applies to JBoss AS version 7 or 7.1.

Previous versions of JBoss used a file named jboss.xml to set these things.  JBoss AS 7.x uses a different file named jboss-webservices.xml instead.  And, the new file doesn't go in the same place as the old file.

If you have a contextual backdrop of general JBoss knowledge, the information you need is reasonably complete here:  https://community.jboss.org/wiki/JBossWS4MigrationGuide  Otherwise, you probably need some of that context too.

Context:
Building an EAR for deployment in JBoss 7, which contains an EJB3 jar file as a module, using maven to build the jar and the ear file, gives you, by default, a really UGLY context path for the EJB WebService endpoint that shows the entire name of the jar artifact.  For instance, if your EJB maven project had an artifactId of WeatherServices-FIVE-DAY-FORECAST-EJB, and its version was 1.0.0-SNAPSHOT, then the jar artifact name would probably be WeatherService-FIVE-DAY-FORECAST-EJB-1.0.0-SNAPSHOT.jar.  Thats ok since maven gives us all a healthy shove towards naming jar artifacts in a way that makes it VERY hard to screw up and use the wrong version of some library.

Then you might have Maven build an ear file, using the maven-ear-plugin to include the EJB jar file using an ejbModule directive as follows

<plugin>
  <artifactid>maven-ear-plugin</artifactid>
  <configuration>
    <version>6</version>
    <modules>
      <ejbmodule>
        <groupid>org.example.weather.services</groupid>
        <artifactid>WeatherServices-FIVE-DAY-FORECAST-EJB</artifactid>
      </ejbmodule>
    </modules>
  </configuration>
</plugin>

Then when you deploy that ear to JBoss AS 7, you get an endpoint address something like

http://yourserver:8080/WeatherService-FIVE-DAY-FORECAST-EJB-1.0.0-SNAPSHOT/WeatherService/WeatherService

Suppose what you wanted was more like this:

http://yourserver:8080/forecast5/WeatherService/WeatherService

After days of googling and guessing (hopefully fewer days if you find this first), you figure out that you need the file called jboss-webservices.xml in the EJB jar's META-INF directory, and it has to have contents like the following:

<?xml version="1.0" encoding="UTF-8"?>
<webservices version="1.0" 
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
       xmlns="http://www.jboss.com/xml/ns/javaee" 
       xsi:schemalocation="http://www.jboss.com/xml/ns/javaee http://www.jboss.org/j2ee/schema/jboss_webservices_1_0.xsd">
    <context-root>forecast5</context-root>
</webservices>

The things that were not clear from the documentation, which took some trial and error, were:
  1. Does jboss-webservices.xml go in the EJB jar file's META-INF? (yes), or the ear file's META-INF? (no).
  2. Is there a way to specify the context root for an ejbModule in the maven plugin, like you can for a webModule? No. And if you've found a way, please post it in a comment.
  3. Is there an alternative to the @WebContext jboss specific annotation in the EJB @Stateless class for a JAX-WS service?  Apparently not.  The port-component tag in jboss-webservices.xml is supposedly intended only to configure JAX-RPC services.  See: https://community.jboss.org/thread/195876

4 comments:

RB Whitaker said...

This solved my problem! Some days, I don't know why I put up with the headaches JBoss gives me...

Unknown said...

Thank you, thank you, thank you! I only spent hours looking for this instead of days (which from this totally obscure answer, I can easily see spending days on this).

Manuel Franqueira said...

Thanks a lot!!!!

Giancarlo Compagno said...

Hi, you can configure your contextRoot in ejbModule using bundleFileName property:
In my ear module I have

<ejbModule>
<groupId>it.myservice</groupId>
<artifactId>myservice</artifactId>
</ejbModule>

and my url is:
http://localhost:8080/myservice-3.0.0-SNAPSHOT/ProfileService/ProfileServiceImpl

now if you add bundleFileName property, you have:

<ejbModule>
<groupId>it.myservice</groupId>
<artifactId>myservice</artifactId>
<bundleFileName>simpleservice.jar</bundleFileName>
</ejbModule>

and new url is

http://localhost:8080/simpleservice/ProfileService/ProfileServiceImpl


It's very important using .jar extension in new name.

Regards,
Giancarlo