Hot questions for Using Enterprise JavaBeans in tomcat

Question:

I am trying to deploy our application through war file to Tomcat on a new server (RHEL 6.9) and ran into java.lang.NoClassDefFoundError: com/ibm/security/certclient/util/PkSsCertFactory. We have deployed the same application version on other existing servers and there is no issue on those.

This is a new server and we are deploying this war for the first time. We do have some custom libraries under ***/Tomcat8/catalinabasedirs/catalinabase0/customlib and have ensured that the version of the jar files under it are same as our other existing servers.

To give more context this application talks to other EJB apps and the mentioned bean ApplicationNameServiceMonitor is to check connectivity to one of the EJB applications.

I am trying to get the jar file containing this class and dig into it to troubleshoot further, meantime thought of posting the question here to get some help.

Following are the details:

Tomcat version: 8.0.x Java Home: ***/Tomcat8/reference/jdk1.7.0_121/jre JVM Version: 1.7.0_121-b32

Spring app context file containing this bean>> resources/appcheck/monitor.xml

<beans profile="xyz,abc,applicationname">
    <bean id="ApplicationNameServiceMonitor" class="com.mycomany.bbs.group.xy.monitor.MonitorFactory" factory-method="createMonitor" init-method="registerMonitor" c:type="wasejb">
        <property name="disable" value="${applicationnameservice.monitor.disable}" />
        <property name="service" value="${applicationnameservice.name}" />
        <property name="contextFactory" value="${applicationnameservice.ejb.jndi.factory}" />
        <property name="url" value="${applicationnameservice.ejb.jndi.url}" />
        <property name="version" value="#{'${applicationnameservice.ejb.address}'.substring(8,16).replace('/','.') + '${applicationnameservice.ejb.address}'.substring(16)}" />
        <property name="ejbs" value="#{'${applicationnameservice.monitor.services}'.split(',')}" />
        <property name="monitorSecurityConfig" ref="monitorSecurityConfigBean"/>
    </bean>
</beans>

Stacktrace

Message Key:CWPKI0043E: Error creating a chained certificate.  The exception that occurred is: java.lang.NoClassDefFoundError: com/ibm/security/certclient/util/PkSsCertFactory. not found in resource bundle:com.ibm.ws.ssl.resources.ssl
org.mule.api.config.ConfigurationException: Error creating bean with name 'ApplicationNameServiceMonitor' defined in class path resource [appcheck/monitor.xml]: Invocation of init method failed; nested exception is java.lang.NoClassDefFoundError: com/ibm/security/certclient/util/PkSsCertFactory (org.mule.api.lifecycle.InitialisationException)
        at org.mule.config.builders.AbstractConfigurationBuilder.configure(AbstractConfigurationBuilder.java:49)
        at org.mule.config.builders.AbstractResourceConfigurationBuilder.configure(AbstractResourceConfigurationBuilder.java:69)
        at org.mule.context.DefaultMuleContextFactory$2.configure(DefaultMuleContextFactory.java:108)
        at org.mule.context.DefaultMuleContextFactory.doCreateMuleContext(DefaultMuleContextFactory.java:222)
        at org.mule.context.DefaultMuleContextFactory.createMuleContext(DefaultMuleContextFactory.java:103)
        at org.mule.config.builders.MuleXmlBuilderContextListener.createMuleContext(MuleXmlBuilderContextListener.java:165)
        at org.mule.config.builders.MuleXmlBuilderContextListener.initialize(MuleXmlBuilderContextListener.java:94)
        at org.mule.config.builders.MuleXmlBuilderContextListener.contextInitialized(MuleXmlBuilderContextListener.java:70)
        at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4884)
        at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5347)
        at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:145)
        at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:755)
        at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:731)
        at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:717)
        at org.apache.catalina.startup.HostConfig.deployWAR(HostConfig.java:973)
        at org.apache.catalina.startup.HostConfig$DeployWar.run(HostConfig.java:1849)
        at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)
        at java.util.concurrent.FutureTask.run(FutureTask.java:262)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
        at java.lang.Thread.run(Thread.java:745)
Caused by: org.mule.api.lifecycle.InitialisationException: Error creating bean with name 'ApplicationNameServiceMonitor' defined in class path resource [appcheck/monitor.xml]: Invocation of init method failed; nested exception is java.lang.NoClassDefFoundError: com/ibm/security/certclient/util/PkSsCertFactory
        at org.mule.registry.AbstractRegistry.initialise(AbstractRegistry.java:112)
        at org.mule.config.spring.SpringXmlConfigurationBuilder.createSpringRegistry(SpringXmlConfigurationBuilder.java:177)
        at org.mule.config.spring.SpringXmlConfigurationBuilder.doConfigure(SpringXmlConfigurationBuilder.java:100)
        at org.mule.config.builders.WebappMuleXmlConfigurationBuilder.doConfigure(WebappMuleXmlConfigurationBuilder.java:79)
        at org.mule.config.builders.AbstractConfigurationBuilder.configure(AbstractConfigurationBuilder.java:43)
        ... 20 more
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'ApplicationNameServiceMonitor' defined in class path resource [appcheck/monitor.xml]: Invocation of init method failed; nested exception is java.lang.NoClassDefFoundError: com/ibm/security/certclient/util/PkSsCertFactory
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1589)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:554)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483)
        at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
        at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
        at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
        at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:759)
        at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:866)
        at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:542)
        at org.mule.config.spring.SpringRegistry.doInitialise(SpringRegistry.java:108)
        at org.mule.registry.AbstractRegistry.initialise(AbstractRegistry.java:104)
        ... 24 more
Caused by: java.lang.NoClassDefFoundError: com/ibm/security/certclient/util/PkSsCertFactory
        at com.ibm.ws.ssl.config.CertificateManager.selfSignedCertificateCreate(CertificateManager.java:212)
        at com.ibm.ws.ssl.config.CertificateManager.chainedCertificateCreate(CertificateManager.java:345)
        at com.ibm.ws.ssl.config.KeyStoreManager.checkIfClientKeyStoreAndTrustStoreExistsAndCreateIfNot(KeyStoreManager.java:1432)
        at com.ibm.ws.ssl.config.SSLConfigManager.addSSLConfigToMap(SSLConfigManager.java:3135)
        at com.ibm.ws.ssl.config.SSLConfigManager.addSSLConfigToMap(SSLConfigManager.java:3113)
        at com.ibm.ws.ssl.config.SSLConfigManager.parseSSLConfigURL(SSLConfigManager.java:3032)
        at com.ibm.ws.ssl.config.SSLConfigManager.initializeClientSSL(SSLConfigManager.java:420)
        at com.ibm.websphere.ssl.JSSEHelper.getInstance(JSSEHelper.java:308)
        at com.ibm.ws.security.orbssl.WSSSLClientSocketFactoryImpl$1.run(WSSSLClientSocketFactoryImpl.java:200)
        at com.ibm.ws.security.util.AccessController.doPrivileged(AccessController.java:118)
        at com.ibm.ws.security.orbssl.WSSSLClientSocketFactoryImpl.createSSLSocket(WSSSLClientSocketFactoryImpl.java:198)
        at com.ibm.ws.orbimpl.transport.WSSSLTransportConnection.createSocket(WSSSLTransportConnection.java:236)
        at com.ibm.CORBA.transport.TransportConnectionBase.connect(TransportConnectionBase.java:344)
        at com.ibm.ws.orbimpl.transport.WSTransport$1.run(WSTransport.java:503)
        at com.ibm.ws.security.util.AccessController.doPrivileged(AccessController.java:118)
        at com.ibm.ws.orbimpl.transport.WSTransport.getConnection(WSTransport.java:500)
        at com.ibm.CORBA.transport.TransportBase.getConnection(TransportBase.java:180)
        at com.ibm.rmi.iiop.TransportManager.get(TransportManager.java:97)
        at com.ibm.rmi.iiop.GIOPImpl.getConnection(GIOPImpl.java:134)
        at com.ibm.rmi.iiop.GIOPImpl.locate(GIOPImpl.java:228)
        at com.ibm.rmi.corba.ClientDelegate.locate(ClientDelegate.java:1738)
        at com.ibm.rmi.corba.ClientDelegate._createRequest(ClientDelegate.java:1763)
        at com.ibm.rmi.corba.ClientDelegate.createRequest(ClientDelegate.java:1054)
        at com.ibm.rmi.corba.ClientDelegate.createRequest(ClientDelegate.java:1131)
        at com.ibm.CORBA.iiop.ClientDelegate.createRequest(ClientDelegate.java:1506)
        at com.ibm.rmi.corba.ClientDelegate.createRequest(ClientDelegate.java:1032)
        at com.ibm.CORBA.iiop.ClientDelegate.createRequest(ClientDelegate.java:1472)
        at com.ibm.rmi.corba.ClientDelegate.request(ClientDelegate.java:1657)
        at com.ibm.CORBA.iiop.ClientDelegate.request(ClientDelegate.java:1428)
        at org.omg.CORBA.portable.ObjectImpl._request(ObjectImpl.java:449)
        at com.ibm.WsnBootstrap._WsnNameServiceStub.getProperties(_WsnNameServiceStub.java:38)
        at com.ibm.ws.naming.util.WsnInitCtxFactory.mergeWsnNSProperties(WsnInitCtxFactory.java:1550)
        at com.ibm.ws.naming.util.WsnInitCtxFactory.getRootContextFromServer(WsnInitCtxFactory.java:1043)
        at com.ibm.ws.naming.util.WsnInitCtxFactory.getRootJndiContext(WsnInitCtxFactory.java:963)
        at com.ibm.ws.naming.util.WsnInitCtxFactory.getInitialContextInternal(WsnInitCtxFactory.java:615)
        at com.ibm.ws.naming.util.WsnInitCtx.getContext(WsnInitCtx.java:128)
        at com.ibm.ws.naming.util.WsnInitCtx.getContextIfNull(WsnInitCtx.java:765)
        at com.ibm.ws.naming.util.WsnInitCtx.lookup(WsnInitCtx.java:164)
        at com.ibm.ws.naming.util.WsnInitCtx.lookup(WsnInitCtx.java:179)
        at javax.naming.InitialContext.lookup(InitialContext.java:411)
        at com.mycomany.bbs.group.xy.monitor.ejb.WASEjbSubSystemMonitor.<init>(WASEjbSubSystemMonitor.java:91)
        at com.mycomany.bbs.group.xy.monitor.ejb.WASEjbServiceMonitor.registerMonitor(WASEjbServiceMonitor.java:32)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:606)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeCustomInitMethod(AbstractAutowireCapableBeanFactory.java:1719)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1656)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1585)
        ... 35 more

Answer:

Resolved the issue. This turned out to be totally different issue. The path to the jks file which we were referring to as keystore and truststore in our jvm argument was incorrect and that cause the code flow to go through the exceptional scenario where it tried to load certain class (that's what I concluded) and the jar for which was missing causing the exception. Since the pom dependency for the aforementioned jar was specified as provided it never complains in build etc. and failed only for this particular scenario occurred.

Question:

A lot of web resources say that Spring Bean is similar to EJB. The Spring bean also as EJB can define the logic via @Component, @Bean and @Service.

But EJBs cannot be run in servlet container like Tomcat.

What is key difference between EJB and Spring Beans?


Answer:

It is not that much about what is the difference between Spring bean and EJB but how beforementioned are managed.

Plain EJBeans or Spring beans do not have any special magic or functionality themselves. The functionality related is implemented in the environment that beans are run.

When you run Spring application in Tomcat you actually run bunch of stuff from Spring framework that makes Spring beans work so not only the beans but lots of other code also that makes autowiring of services & components etc.. happen.

However when you implement JavaEE with EJB all of the stuff you deploy consists only of your business code and beans not anything like Spring that has the managing logic also included.

So EJB / JavaEE you need this managing stuff separately and this is why plain Tomcat is not enough for EJB. You need an J2EE container in which you run your EJBs for example - TomEE that is an extension having OpenEJB with Tomcat or see a list of Certified referencing runtimes (about in the middle of the Wikipage behind link).

See also this and this related more or less.

Question:

I have the following setup in my application:

ABCAPI.java (TestAPIInterface.jar)

public void search(FormData data);

ABCAPIBean.java (TestAPI.ear)

public void search(FormData data) 
{
    //log
    //more code
}

ABCAction.java (TestUI.war)

public void loadList(session) {
     //get ABCAPIBean
     api.search(loadFormData(session));
}
public FormData loadFormData(session) {
     //get some information from ABCCore class based on form filters
}

ABCCore.java (TestCore.jar)

Deployed the following packages in JBoss, tomcat servers

JBoss Clusters (node1, node2)

TestAPI.ear
TestAPIInterface.jar
TestCore.jar

Tomcat Web servers (node1, node2)

TestUI.war
TestAPIInterface.jar
TestCore.jar

Everything seems to be working fine until I made a few code changes to ABCCore.java file & deployed latest TestCore.jar into all servers.

Now when accessing the UI, I am getting results and error alternatively. When I checked the logs, whenever UI application requests ABCAPIBean from node1, it is throwing error 'InvalidObjectException', and when it requests from node2, it is giving results. This is happening with the new constant introduced in 'ABCCore.java'.

One possible issue is with the latest jar but I eliminated it by copying TestCore.jar from node2 to node1. I still see the same issue in node1. Any other suggestions ?

P.S: I don't see log statement (ABCAPIBean) in Jboss node1 but I see it in Jboss node2. InvalidObjectException is coming in the tomcat UI log


Answer:

This looks like a deployment error. If you're sure you have the good versions of your jar and war files respectively on your servers, you can try a cleaning of the deployments.

In Tomcat, stop the process, remove the work directory content, and start again. There's also a similar work directory in JBOSS, and you could proceed the same way (stop, clean, start).

By the way you didn't say if you are on Windows or Linux. There were old bugs on Tomcat on Windows, called "jar locking" that could give these kind of errors.

Question:

In our current production stack we have different types of workloads, many of them HTTP related and running in Tomcat containers, but we also have some other kind of workloads, which have been split into self managed standalone applications and war files that fire up cron-like jobs, queue (MQTT & SNS) listeners and, daemon kind of servers for IoT devices which have tons of different TCP protocols.

We are aware that standalone apps are not easy to manage and running the above kind of services in Tomcat containers is not entirely correct too, so I'm asking what are the best practices for running such services and/or what are the nowadays containers for these purposes.

I know that EJBs might work for some of these scenarios, but could be quite an overhead to use them, so I'm trying to find more options.

PS: 99% of of software is built in Java, so that's a heavy constraint for our possible choices.


Answer:

Sounds like you might want a full-blown ESB (Enterprise Service Bus), though that's probably overkill.

If you look at the Products section of the Wikipedia page linked above, you'll find multiple options.

However, if you're just looking for the communication layer, rather than a full ESB, you could use something like Apache CXF, which is used by the Apache ServiceMix ESB.

Haven't used it myself, but it supports multiple transport layers, such as HTTP, JMS, WebSocket, and CORBA, which seems to be what you're looking for.

Question:

I have my T3 client code like this:

private InitialContext initContext() {
    Properties p = new Properties();
    p.put(Context.INITIAL_CONTEXT_FACTORY, "weblogic.jndi.WLInitialContextFactory");
    p.put(Context.PROVIDER_URL, context.providerURL);

    for (Map.Entry<String, String> entry : getEnvironmentProperties().entrySet()) {
        p.put(entry.getKey(), entry.getValue());
    }

    InitialContext res = null;
    try {
        res = new InitialContext(p);
    } catch (NamingException e) {
        e.printStackTrace();
    }

    return res;
}

My t3 client deployed on Tomcat (uses wlthint3client-12.1.3.jar) and trying to lookup remote bean of external system which deployed on Weblogic.

However when I trying to perform new InitialContext(p) I receive SSLHandshake exception, because it gets standart SSLSocketFactory with standart SSLConext and standart java trust store.

My question - is there any way to give to InitialContext some property which will override SSLSocketFacory. My aim is to populate my cutom trust store to this t3 client.

Changing standart trust store like this

System.setProperty("javax.net.ssl.trustStore", "pathToTrustStore"); 

works fine, however in case if my t3 client is used to communicate with 2 different external systems, it might be a problem in doing so.

Is there some property that I can populate?

Properties p = new Properties();
p.put(Context.INITIAL_CONTEXT_FACTORY, "weblogic.jndi.WLInitialContextFactory");
**p.put("CUSTOM SSL SOCKET FACTORY, "MY CLASS");**

Answer:

Problem was solved by adding few parameters on application side

export JAVA_OPTS ="$JAVA_OPTS -Djavax.net.ssl.trustStore=path/truststore.jks"
export JAVA_OPTS ="$JAVA_OPTS -Djavax.net.ssl.trustStorePassword=changeIT"