Friday, December 21, 2007

EJB 3.0 and 4 different Application Servers - Good, bad or ugly.

I have been writing EJB 3.0 application from the past 3 months. I am not yet sure what application server we are going to use. I was initially testing with JBoss, but as you might have seen in my previous posts on this blog, I can't get JBoss to work with Java 6 as well as web services.

Just to remind you I had no deployment descriptor for any of these servers. That's one of the big things for EJB 3.0, right? EJB 3.0 specification states that the deployment descriptor is not necessary.

You just have to add annotations, and that's what I did. If you can't deploy one simple application to various servers, does it make any sense to say EJB 3.0 applications are portable. They should be as per the EJB 3.0 spec.

The next course I took was to write a simple, really simple Stateless Session Bean. Just one method in it, publish it as a web service and try to deploy the same on the following Application Servers. I have used and administered JBoss, WebLogic,and WebSphere. But, in this case I used some different ones. It's up to you to decide which ones are good, bad, and ugly.

1. JBoss
2. GlassFish V2
3. Oracle Application Server
4. WebLogic 10.

Here is my remote interface for the stateless session bean:

package ejb3.ws.biz;
import javax.ejb.Remote;

@Remote
public interface HelloManager
{
public String sayHello(String serverName);

}


And here is my simple session bean class:

package ejb3.ws.biz;

import javax.ejb.Stateless;
import javax.jws.WebMethod;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;


@WebService(name="HelloManager", targetNamespace = "urn:HelloManagerService")
@SOAPBinding(style = SOAPBinding.Style.RPC)
@Stateless(name="HelloManager")
public class HelloManagerBean implements HelloManager
{

@WebMethod
public String sayHello(String serverName)
{
return "I am saying hello from " + serverName;
}
}

Compiled the classes, jarred them up, and tried deploying to each one of the above mentioned application servers.

1. GlassFish V2: This was the first time I was using GlassFish. I used the Admin Console, deployed the file, used the page to test the web services. Surprise surprise, it works. Hurray.

2. Oracle Application Server: Again, this was the first time I was using Oracle AS. I used the Admin Console, deployed the file. And this time, I tested with SoapUI, and web services worked like a charm.

3. JBoss 4.2.1: The same application which deployed and worked on the above 2 app servers, did deploy fine in this case. No exceptions at all. But when I used SoapUI to test my one and only one web service, it failed miserably. Here comes the stack trace:

2007-12-20 12:44:04,779 ERROR [org.apache.catalina.core.ContainerBase.[jboss.web].[localhost].[/HelloManagerBeanService].[HelloManager]] Servlet.service() for servlet HelloManager threw exception java.lang.UnsupportedOperationException: setProperty must be overridden by all subclasses of SOAPMessage at javax.xml.soap.SOAPMessage.setProperty(SOAPMessage.java:424) at org.jboss.ws.core.soap.SOAPMessageImpl.(SOAPMessageImpl.java:67) at org.jboss.ws.core.soap.MessageFactoryImpl.createMessage(MessageFactoryImpl.java:155) at org.jboss.ws.core.jaxws.SOAPFaultHelperJAXWS.toSOAPMessage(SOAPFaultHelperJAXWS.java:235) at org.jboss.ws.core.jaxws.SOAPFaultHelperJAXWS.exceptionToFaultMessage(SOAPFaultHelperJAXWS.java:164) at org.jboss.ws.core.jaxws.binding.SOAP11BindingJAXWS.createFaultMessageFromException(SOAP11BindingJAXWS.java:104) at org.jboss.ws.core.CommonSOAPBinding.bindFaultMessage(CommonSOAPBinding.java:623) at org.jboss.ws.core.server.ServiceEndpoint.processRequest(ServiceEndpoint.java:229) at org.jboss.ws.core.server.ServiceEndpointManager.processRequest(ServiceEndpointManager.java:448) at org.jboss.ws.core.server.AbstractServiceEndpointServlet.doPost(AbstractServiceEndpointServlet.java:114) at javax.servlet.http.HttpServlet.service(HttpServlet.java:710) at org.jboss.ws.core.server.AbstractServiceEndpointServlet.service(AbstractServiceEndpointServlet.java:75) at javax.servlet.http.HttpServlet.service(HttpServlet.java:803) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) at org.jboss.web.tomcat.filters.ReplyHeaderFilter.doFilter(ReplyHeaderFilter.java:96) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:230) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175) at org.jboss.web.tomcat.security.SecurityAssociationValve.invoke(SecurityAssociationValve.java:179) at org.jboss.web.tomcat.security.JaccContextValve.invoke(JaccContextValve.java:84) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128) at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:104) at org.jboss.web.tomcat.service.jca.CachedConnectionValve.invoke(CachedConnectionValve.java:157) at org.apache.catalina.core.SandardEngineValve.invoke(StandardEngineValve.java:109) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:241) at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:844) at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:580) at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:447) at java.lang.Thread.run(Thread.java:619)


4. WebLogic 10. I have been using WebLogic server from version 8 onwards. So, I was very confident it would work. Here again, I used the Admin Console to deploy the application, but nope. It didn't want to deploy at any cost. I didn't even bother to goggle and find out why it was throwing an exception. It says error occurred while reading the deployment descriptor, why? I don't have one, I have just annotations.

Is it mandatory to have a
deployment descriptor in WebLogic for EJB 3.0 applications? The EJB 3.0 specification states that the deployment descriptor is not necessary. I don't know, and I won't even bother to find out.

Here comes the stack trace:

[EJB:011023]An error occurred while reading the deployment descriptor. The error was: : java.lang.ClassNotFoundException: Class bytes found but defineClass()failed for: 'ejb3.ws.biz.HelloManagerBean'.' weblogic.application.ModuleException: Exception preparing module: EJBModule(ejb3businesstier.jar) [EJB:011023]An error occurred while reading the deployment descriptor. The error was: : java.lang.ClassNotFoundException: Class bytes found but defineClass()failed for: 'ejb3.ws.biz.HelloManagerBean'. at weblogic.ejb.container.deployer.EJBModule.prepare(EJBModule.java:399) at weblogic.application.internal.flow.ModuleListenerInvoker.prepare(ModuleListenerInvoker.java:93) at weblogic.application.internal.flow.DeploymentCallbackFlow$1.next(DeploymentCallbackFlow.java:360) at weblogic.application.utils.StateMachineDriver.nextState(StateMachineDriver.java:26) at weblogic.application.internal.flow.DeploymentCallbackFlow.prepare(DeploymentCallbackFlow.java:56) at weblogic.application.internal.flow.DeploymentCallbackFlow.prepare(DeploymentCallbackFlow.java:46) at weblogic.application.internal.BaseDeployment$1.next(BaseDeployment.java:615) at weblogic.application.utils.StateMachineDriver.nextState(StateMachineDriver.java:26) at weblogic.application.internal.BaseDeployment.prepare(BaseDeployment.java:191) at weblogic.application.internal.DeploymentStateChecker.prepare(DeploymentStateChecker.java:147) at weblogic.deploy.internal.targetserver.AppContainerInvoker.prepare(AppContainerInvoker.java:61) at weblogic.deploy.internal.targetserver.operations.ActivateOperation.createAndPrepareContainer(ActivateOperation.java:189) at weblogic.deploy.internal.targetserver.operations.ActivateOperation.doPrepare(ActivateOperation.java:87) at weblogic.deploy.internal.targetserver.operations.AbstractOperation.prepare(AbstractOperation.java:217) at weblogic.deploy.internal.targetserver.DeploymentManager.handleDeploymentPrepare(DeploymentManager.java:719) at weblogic.deploy.internal.targetserver.DeploymentManager.prepareDeploymentList(DeploymentManager.java:1186) at weblogic.deploy.internal.targetserver.DeploymentManager.handlePrepare(DeploymentManager.java:248) at weblogic.deploy.internal.targetserver.DeploymentServiceDispatcher.prepare(DeploymentServiceDispatcher.java:157) at weblogic.deploy.service.internal.targetserver.DeploymentReceiverCallbackDeliverer.doPrepareCallback(DeploymentReceiverCallbackDeliverer.java:157) at weblogic.deploy.service.internal.targetserver.DeploymentReceiverCallbackDeliverer.access$000(DeploymentReceiverCallbackDeliverer.java:12) at weblogic.deploy.service.internal.targetserver.DeploymentReceiverCallbackDeliverer$1.run(DeploymentReceiverCallbackDeliverer.java:45) at weblogic.work.SelfTuningWorkManagerImpl$WorkAdapterImpl.run(SelfTuningWorkManagerImpl.java:464) at weblogic.work.ExecuteThread.execute(ExecuteThread.java:200) at weblogic.work.ExecuteThread.run(ExecuteThread.java:172) java.io.IOException: : java.lang.ClassNotFoundException: Class bytes found but defineClass()failed for: 'ejb3.ws.biz.HelloManagerBean' at weblogic.ejb.container.dd.xml.EjbDescriptorReaderImpl.processStandardAnnotations(EjbDescriptorReaderImpl.java:324) at weblogic.ejb.container.dd.xml.EjbDescriptorReaderImpl.createReadOnlyDescriptorFromJarFile(EjbDescriptorReaderImpl.java:186) at weblogic.ejb.spi.EjbDescriptorFactory.createReadOnlyDescriptorFromJarFile(EjbDescriptorFactory.java:93) at weblogic.ejb.container.deployer.EJBModule.loadEJBDescriptor(EJBModule.java:965) at weblogic.ejb.container.deployer.EJBModule.prepare(EJBModule.java:335) at weblogic.application.internal.flow.ModuleListenerInvoker.prepare(ModuleListenerInvoker.java:93) at weblogic.application.internal.flow.DeploymentCallbackFlow$1.next(DeploymentCallbackFlow.java:360) at weblogic.application.utils.StateMachineDriver.nextState(StateMachineDriver.java:26) at weblogic.application.internal.flow.DeploymentCallbackFlow.prepare(DeploymentCallbackFlow.java:56) at weblogic.application.internal.flow.DeploymentCallbackFlow.prepare(DeploymentCallbackFlow.java:46) at weblogic.application.internal.BaseDeployment$1.next(BaseDeployment.java:615) at weblogic.application.utils.StateMachineDriver.nextState(StateMachineDriver.java:26) at weblogic.application.internal.BaseDeployment.prepare(BaseDeployment.java:191) at weblogic.application.internal.DeploymentStateChecker.prepare(DeploymentStateChecker.java:147) at weblogic.deploy.internal.targetserver.AppContainerInvoker.prepare(AppContainerInvoker.java:61) at weblogic.deploy.internal.targetserver.operations.ActivateOperation.createAndPrepareContainer(ActivateOperation.java:189) at weblogic.deploy.internal.targetserver.operations.ActivateOperation.doPrepare(ActivateOperation.java:87) at weblogic.deploy.internal.targetserver.operations.AbstractOperation.prepare(AbstractOperation.java:217) at weblogic.deploy.internal.targetserver.DeploymentManager.handleDeploymentPrepare(DeploymentManager.java:719) at weblogic.deploy.internal.targetserver.DeploymentManager.prepareDeploymentList(DeploymentManager.java:1186) at weblogic.deploy.internal.targetserver.DeploymentManager.handlePrepare(DeploymentManager.java:248) at weblogic.deploy.internal.targetserver.DeploymentServiceDispatcher.prepare(DeploymentServiceDispatcher.java:157) at weblogic.deploy.service.internal.targetserver.DeploymentReceiverCallbackDeliverer.doPrepareCallback(DeploymentReceiverCallbackDeliverer.java:157) at weblogic.deploy.service.internal.targetserver.DeploymentReceiverCallbackDeliverer.access$000(DeploymentReceiverCallbackDeliverer.java:12) at weblogic.deploy.service.internal.targetserver.DeploymentReceiverCallbackDeliverer$1.run(DeploymentReceiverCallbackDeliverer.java:45) at weblogic.work.SelfTuningWorkManagerImpl$WorkAdapterImpl.run(SelfTuningWorkManagerImpl.java:464) at weblogic.work.ExecuteThread.execute(ExecuteThread.java:200) at weblogic.work.ExecuteThread.run(ExecuteThread.java:172)

21 comments:

  1. Doesn't Oracle use the JAX-WS implementation from Glassfish? I know JBoss wrote their own.

    How does it perform if you leave out the SoapBinding annotation? Isn't doc/literal the default in .Net and preferred method in Java now?

    ReplyDelete
  2. Oracle wasn't a problem at all.

    It works fine if the SoapBinding annotation is removed.

    Yes, doc/literal is the default.

    I wanted to test RPC, that's the reason I added it.

    ReplyDelete
  3. You might want to give it a try with JBoss 4.2.2. The release notes mention an upgrade of JAX-WS.

    ReplyDelete
  4. Nope, It didn't work. I do see that JBoss 5.0 Beta 3 was released yesterday. I will give that a try as well.

    ReplyDelete
  5. I have made the same experiences.

    Glassfish works out of the box. JBoss throws an exception first, requires you to look throw forums and wikis for some stupid solution and works after 2 days. If it does not work after 2 days, you post at their forum and get the answer that this is a known issue, that will be solved either in the next version (which is a few months away) or wont be solved and you will be asked to write a solution yourself and provide the patch in their JIRA. It is OpenSource after all!


    Glassfish is way too awesome to not use it. It is Websphere with JBoss AS price label attached.


    I am looking forward for Glassfish v3, where you can deploy Java (of course Groovy, too), JRuby and even PHP apps.

    ReplyDelete
  6. Yes, indeed. My experience with GlassFish is the same as well.

    I am trying Oracle Application Server also, it is working well for me.

    ReplyDelete
  7. Thanks for your kind words on GlassFish, Meera. If you need anything around GlassFish, just drop us an email, either at the USERS@glassfish.dev.java.net alias, or directly to me - either at TheAquarium or at Sun.

    ReplyDelete
  8. Thanks for information. I've been using Glassfish for some time and so no problem at all. Moreover it has a very great community/forum support.

    ReplyDelete
  9. Hi Pelegri,
    Thanks for your comments. Sure, I will keep you posted if I encounter any problems.

    ReplyDelete
  10. You mentioned something about java 6, are you either compiling to or running Weblogic on 6? I was getting similar errors when trying to deploy anything to Weblogic 10, until I switched the compile and runtime for it to Java 5 instead, worked fine after that. YMMV ;) Mike

    ReplyDelete
  11. I am compiling to Java 5. WebLogic runs under its own JVM, doesn't it?

    ReplyDelete
  12. Meera,

    As it comes to JBoss. This is unfair to compare "compability level" wit fully JEE 5 certified servers like GlassFish v2 or WLS10 and JBoss 4.2.1, which, as it is clearly stated by RedHat has *preliminary* and *experimantal* J2EE stuff, especially on the edges. Especially if it comes to JAXWS, what You actually tested. Also if You would read Release notes for JBoss 4.2.1 You would read exactly this: "JDK6 is not formally supported yet".

    BTW. Your example forks for me with JBoss 4.2.2 and JDK5.

    ReplyDelete
  13. Artur,
    I wanted an Application Server which worked for Java 6 and EJB 3.0.
    I was just making notes as I worked with each one of them.
    Yes, I have read the release notes for each ones of these and tried all workaround as well.
    BTW, even with the latest JBoss 5.0 beta 3, the server does start with Java 6 after adding one system property, but web services doesn't work at all.

    ReplyDelete
  14. I have exactly the same trouble with Weblogic10:
    java.io.IOException: : java.lang.ClassNotFoundException: Class bytes found but defineClass()failed for: 'electricstore.ejb.ShoppingCartBean'

    Did you found a solution?

    ReplyDelete
  15. Even though the specification doesn't mandate having the ejb-jar.xml, WebLogic requires one. I think I found this in one of their forums. So, add the DD and you should be able to deploy the app.

    ReplyDelete
  16. The reason for the byte discrepancy is that you compiled in jdk6.0 and WebLogic runs under 5.0

    ReplyDelete
  17. I don't understand, I did set the source version in the javac command to 1.5.

    ReplyDelete
  18. Source vs target:
    -source means to use source compatibility, -target means to create class files that work with a certain version.

    Use -target instead.

    ReplyDelete
  19. I've just did the same with weblogic 10.0.1 and there was no problems.
    I compiled sources with jdk_1.5.0_12 and weblogic also works on the same jdk.
    So when I deployed jar archive with ejb30(without ejb-jar, only annotations) there was no excpetions and my EJB can work as WebService.

    ReplyDelete
  20. Hi,
    When we require enterprise scaling, which are our options?
    Regards
    rrajan

    ReplyDelete
  21. I faced the same issue while trying to publish my project similar to the above described in weblogic 10.3.6, with java 1.7. Later i solved it by changing all the default references of java 1.6 in the properties, java build path, Java compiler,project facets, domain specifications(edited the JAVA _HOME path setDomainEnv.cmd in domain/domain name/bin folder ). Once all the reference of the previous version is changed to new one. everything works fine.

    ReplyDelete