Aeron messaged consumed twice when concurrent messages published - java

I'm toying with a websocket server that sends messages to an aeron publication. These get consumed by a subscription and this normally works fine. Published messages are consumed by an Agent backed subscription. However, when 2 messages are sent concurrently to the publication, I can see one of the messages consumed twice while the other is not. Any ideas what could be causing this?
I've tried to enable the Aeron Agent but setting it up with the same 1.40 version as the dependencies the project has, it throws this error:
Exception in thread "[sender,receiver,driver-conductor]" java.lang.LinkageError: loader constraint violation: when resolving method 'void io.aeron.agent.DriverEventLogger.log(io.aeron.agent.DriverEventCode, org.agrona.DirectBuffer, int, int)' the class loader io.quarkus.bootstrap.classloading.QuarkusClassLoader #3e6f3bae of the current class, io/aeron/driver/ClientCommandAdapter, and the class loader 'app' for the method's defining class, io/aeron/agent/DriverEventLogger, have different Class objects for the type org/agrona/DirectBuffer used in the signature (io.aeron.driver.ClientCommandAdapter is in unnamed module of loader io.quarkus.bootstrap.classloading.QuarkusClassLoader #3e6f3bae, parent loader 'app'; io.aeron.agent.DriverEventLogger is in unnamed module of loader 'app')
at io.aeron.driver.ClientCommandAdapter.onMessage(ClientCommandAdapter.java:75)
at org.agrona.concurrent.ringbuffer.ManyToOneRingBuffer.read(ManyToOneRingBuffer.java:201)
at io.aeron.driver.ClientCommandAdapter.receive(ClientCommandAdapter.java:66)
at io.aeron.driver.DriverConductor.doWork(DriverConductor.java:216)
at org.agrona.concurrent.CompositeAgent.doWork(CompositeAgent.java:120)
at org.agrona.concurrent.AgentRunner.doWork(AgentRunner.java:304)
at org.agrona.concurrent.AgentRunner.workLoop(AgentRunner.java:296)
at org.agrona.concurrent.AgentRunner.run(AgentRunner.java:162)
at java.base/java.lang.Thread.run(Thread.java:1589)
I've also tried to hook to a running process using the instructions here but it fails saying dynamic agent cannot be found:
$ java -cp ./aeron-all-1.40.0.jar io.aeron.agent.DynamicLoggingAgent ./aeron-agent-1.40.0.jar 61616 start
Error: Could not find or load main class io.aeron.agent.DynamicLoggingAgent
Thanks

Related

WAS 8.5.5 ejb lookup produces invalid object reference com.ibm.ws.naming.util.InvalidObjectException

com.ibm.ws.naming.util.InvalidObjectException: Some object reference in the name "MyEJB" relative to the context "path/to/myserver" is invalid.
Some possible causes include a context binding in the name which refers to a destroyed context, or an object binding which contains an invalid EJBHome reference.
[Root exception is org.omg.CORBA.INV_OBJREF: Could not resolve IOR string. vmcid: 0x0 minor code: 0 completed: No]
The lookup of other ejbs in the app is working. The difference is the bean class of this ejb was modified and only the new class file was updated in the ear and the app was updated with this ear file in WAS admin console.
Do I have to regenerate the deployment code(stub/tie etc) for the ejb?
The EJB deployment code only needs to be regenerated if the bean interfaces have been modified or the signature of the bean implementation methods has changed. If those have not changed, then likely the issue is the bean failed to start. Check the logs (Systemout.log and FFDC logs) for any other errors related to that EJB. The application may have started fine, but typically EJB initialization is deferred until first use, which is often the first time the bean is looked up. Finally, verify the logs contain a CNTR0167I message indicating the bean was bound in JNDI using the lookup name.

ServiceConfigurationError caused by LinkageError in WebSphere

I have an application that is deployed on WebSphere 9.0.5.2 where I want to use CXF for webservice calls and I'm getting this This ServiceConfigurationError
WrapperedException { java.util.ServiceConfigurationError: javax.xml.ws.spi.Provider: Provider org.apache.cxf.jaxws.spi.ProviderImpl could not be instantiated
Further down the stacktrace, I see that this is caused by a LinkageError
Caused by: java.lang.LinkageError: loading constraint violation when overriding method
"javax/xml/ws/spi/ServiceDelegate.createDispatch(Ljavax/xml/namespace/QName;Ljavax/xml/bind/JAXBContext;Ljavax/xml/ws/Service$Mode;)Ljavax/xml/ws/Dispatch;" during creation of class
"org/apache/cxf/jaxws/ServiceImpl": loader
"com/ibm/ws/classloader/CompoundClassLoader#832133d2" of class
"org/apache/cxf/jaxws/ServiceImpl" and loader
"com/ibm/oti/vm/BootstrapClassLoader#2eec706a" of class
"javax/xml/ws/spi/ServiceDelegate" have different types for the method signature
I understand that this could be caused by multiple libraries that have different definitions for QName or JAXBContext, but I think I've ruled those out.
I also understand that WebSphere has it's own JAX-WS with it's own method signature for ServiceDelegate.createDispatch and I've tried setting DisableIBMJAXWSEngine to true in WebSphere as instructed here
Using a third-party JAX-WS web services engine
I still haven't been able to get rid of the error and am pretty much at a loss as to what to try next. Any suggestions is appreciated!!!
The issue here is a cross-linkage between the application and server's copies of the JAXB API, JAX-WS API, and JAX-WS implementation. The application (configured with parent-last class loading delegation, so it searches locally before delegating to parents) contains a JAX-WS implementation and JAXB API/impl, but it does not contain the JAX-WS API. Since JAX-WS references JAXB, we get the following linkage pattern:
1) Some application class references the JAX-WS API. Because it's not packaged in the application, it's loaded from the server libraries.
2) When the API class is linked, it uses its local class loader to find the JAXB API. That, in turn, links it to the server's version as well.
3) JAX-WS uses the thread context class loader to load its implementation. It finds it in the parent-last application.
4) When the implementation class is linked, it uses its local class loader to find the JAXB API, which finds it locally in the application.
5) The implementation now is linked to two versions of the same class:
JAXWSImpl -> JAXWSAPI -> JAXB (server)
JAXWSImpl -> JAXB (app)
The JVM can't tolerate that, and a LinkageError is thrown.
The solution can be approached one of two ways:
1) Add the JAX-WS API to the application - this prevents the initial delegation in #1 above
2) Remove the JAXB API (and implementation, if provided) from the application - this causes the linkage in #4 to delegate down to the server for JAXB, so it's always loaded from the same place.
Either way, the trick is to ensure that all the necessary classes are available to the application through the same class loader.

EJB: Passing instance of concrete class to an EJB method

Lets say there is an EJB method that accepts an object implementing some interface.
MyStatelessBean.method(InterfaceA aObj);
So the server implements MyStatelessBean and the InterfaceA is available in its classpath.
Now the concrete classes of InterfaceA are implemented at the Client side. These concrete classes are not in the classpath of the server.
Now when the client makes a call to the server and passes an instance of the concrete class to EJB method,
InterfaceA concreteObjA = new InterfaceA() { ... }
bean = context.lookup(ejbLookupStr);
bean.method(concreteObjA);
what is the expected behavior?
My testing in WildFly 9.0.2 resulted in ClassNotFoundException being reported in the Client side logs (but it seems like it is reporting a server side issue).
Exception in thread "main" javax.ejb.EJBException:
java.lang.ClassNotFoundException:
org.ktest.study.javaee.ejb.CallBackClient from [Module
"deployment.wildfly-ear.ear.wildfly-ejb.jar:main" from Service Module
Loader] at
org.jboss.ejb.client.EJBInvocationHandler.doInvoke(EJBInvocationHandler.java:238)
at
org.jboss.ejb.client.EJBInvocationHandler.doInvoke(EJBInvocationHandler.java:183)
at
org.jboss.ejb.client.EJBInvocationHandler.invoke(EJBInvocationHandler.java:146)
at com.sun.proxy.$Proxy0.register(Unknown Source) at
org.ktest.study.javaee.ejb.ClientObject.main(ClientObject.java:21)
Answering my own question:
Actually my requirement is server to client callback using RMI. The server provides CallBack Interface. But it's upto the Client to provide the concrete implementation. Since EJB uses serialization to pass objects from clients to server, it requires that the concrete class be available at server side for deserialization.
I had a bug in my RMI code which was causing the error.

Correct way to lookup local EJB in websphere - Getting ClassCastException

I have an EJB which is exposed by both local and remote interfaces
package com.sam.enqueue;
import javax.ejb.Local;
import javax.ejb.Remote;
import javax.ejb.Singleton;
#Singleton
#Local(SamEnqueueLocal.class)
#Remote(SamEnqueueRemote.class)
public class SamEnqueue implements SamEnqueueRemote, SamEnqueueLocal {
}
// remote interface
package com.sam.enqueue;
import javax.ejb.Remote;
#Remote
public interface SamEnqueueRemote {
}
// local interface
package com.sam.enqueue;
#Local
public interface SamEnqueueLocal {
}
My app container is websphere 8.0 and I am not overriding the default JNDI names which the server assigns.
During server startup I get the following default bindings in logs:
CNTR0167I: The server is binding the com.sam.enqueue.SamEnqueueRemote interface of the SamEnqueue enterprise bean in the SAM_ENQUEUE.jar module of the SAM_ENQUEUE application. The binding location is: ejb/SAM_ENQUEUE/SAM_ENQUEUE.jar/SamEnqueue#com.sam.enqueue.SamEnqueueRemote
CNTR0167I: The server is binding the com.sam.enqueue.SamEnqueueRemote interface of the SamEnqueue enterprise bean in the SAM_ENQUEUE.jar module of the SAM_ENQUEUE application. The binding location is: com.sam.enqueue.SamEnqueueRemote
CNTR0167I: The server is binding the com.sam.enqueue.SamEnqueueRemote interface of the SamEnqueue enterprise bean in the SAM_ENQUEUE.jar module of the SAM_ENQUEUE application. The binding location is: java:global/SAM_ENQUEUE/SamEnqueue!com.sam.enqueue.SamEnqueueRemote
CNTR0167I: The server is binding the com.sam.enqueue.SamEnqueueLocal interface of the SamEnqueue enterprise bean in the SAM_ENQUEUE.jar module of the SAM_ENQUEUE application. The binding location is: ejblocal:SAM_ENQUEUE/SAM_ENQUEUE.jar/SamEnqueue#com.sam.enqueue.SamEnqueueLocal
CNTR0167I: The server is binding the com.sam.enqueue.SamEnqueueLocal interface of the SamEnqueue enterprise bean in the SAM_ENQUEUE.jar module of the SAM_ENQUEUE application. The binding location is: ejblocal:com.sam.enqueue.SamEnqueueLocal
CNTR0167I: The server is binding the com.sam.enqueue.SamEnqueueLocal interface of the SamEnqueue enterprise bean in the SAM_ENQUEUE.jar module of the SAM_ENQUEUE application. The binding location is: java:global/SAM_ENQUEUE/SamEnqueue!com.sam.enqueue.SamEnqueueLocal
The lookup class is just a simple java class in a different EAR in the same server with the following code:
Context ctx = new InitialContext();
Object local = ctx.lookup("java:global/SAM_ENQUEUE/SamEnqueue!com.sam.enqueue.SamEnqueueLocal");
SamEnqueueLocal samEnqueue = (SamEnqueueLocal) local;
The lookup is working with any of the three JNDI names for the local but it's not getting cast to SamEnqueueLocal. The exception trace is:
SystemErr R java.lang.ClassCastException: com.sam.enqueue.EJSLocal0SGSamEnqueue_cf56ba6f incompatible with com.sam.enqueue.SamEnqueueLocal
... rest ommited
I've made a shared library and put the stub of destination EAR in it. The library is the classpath of the source lookup EAR with the Classes loaded with local class loader first (parent last) policy. The library is not isolated. If I remove the stub, I get a java.lang.ClassNotFoundException: com.sam.enqueue.SamEnqueueLocal as expected.
Update:
While using Dependency Injection:
#EJB(lookup="ejblocal:com.sam.enqueue.SamEnqueueLocal")
private SamEnqueueLocal samEnqueueLocal;
The error I get is:
javax.ejb.EJBException: Injection failure; nested exception is: java.lang.IllegalArgumentException: Can not set com.sam.enqueue.SamEnqueueLocal field com.some.SomeBean.samEnqueueLocal to com.sam.enqueue.EJSLocal0SGSamEnqueue_cf56ba6f
Caused by: java.lang.IllegalArgumentException: Can not set com.sam.enqueue.SamEnqueueLocal field com.some.SomeBean.samEnqueueLocal to com.sam.enqueue.EJSLocal0SGSamEnqueue_cf56ba6f
So it's basically the same.
You are getting java.lang.ClassCastException because you are retrieving a reference to an EJB that exists in a different class loader than the deployment unit (ejb-jar, war, etc) that is trying to inject it.
Using local EJB references between applications is vendor dependent if possible at all. You may be able to deploy your SamEnqueue bean in a separate EJB module and try to reference it via a manifest Class-Path: entry from each application. Be sure that there are no copies of SamEnqueueLocal in either EAR file.
Alternatively, just use the SamEnqueueRemote interface.
Refer to chapter 8 of the Java EE specification for more information.
See the "Local client views" section of the EJB modules topic in the knowledge center:
The EJB specification only requires local client views to be supported
for EJBs packaged within the same application. This includes local
homes, local business interfaces, and the no-interface view.
WebSphere® Application Server permits access to local client views to
EJBs packaged within a separate application with some restrictions
The local interface and all parameter, return, and exception types used by the local interface must be visible to the class loader of both the calling application and the target EJB application. You can ensure this by either using a shared library associated with a server class loader or by using an isolated shared library associated with both applications. Read the Creating shared libraries topic for more information.
...
From the link provided by in bkail's answer, These are the steps that I followed to make it work.
Take out the Local and Remote interfaces i.e. SamEnqueueRemote and SamEnqueueLocal from my source EJB jar and package then into a separate jar file. Although just taking out the Local interface will also work.
Make a shared library and put this jar into it. The shared library must be isolated so that same version of class is loaded by caller and callee.
In the caller EAR, get a reference to the local interface with either a lookup or injection.
Deploy both the caller and callee to the server and make sure to add the shared library in the classpath of both the EARs.
One of the approaches mentioned in this link is similar.
One way to prevent this is to use a remote interface. As Paul mentioned, there is optimization that happens when the caller and callee are in the same JVM, so it's not as expensive as if they're in separate JVMs. The ORB has classloader machinery that ensures the classes for the caller and callee are loaded using classloaders compatible with each side of the call.
Option 2, including the ejb jar within the new ear, won't solve the problem. Even though the classes will be available in both classloaders, the object passed by-reference from callee back to caller will still be instanciated using the other application's classloader and will not be type-assignable. Same with Option 3.
The 2nd way to make it work is to place the classes used by caller and callee in a "WAS shared library" and configure both applications to use that shared library. The subject of shared libraries and how to configure them is described in the WAS InfoCenter documentation...search on "shared library."
The 3rd way to make it work, which is the least desirable of the three, is to change the WAS server classloader policy to "one classloader per server." The default, as I mentioned at the top, is "one classloader per application (EAR file)." Changing to one classloader per server ensures that everything gets loaded by the same classloader and is thus type-compatible, but deprives your applications of the isolation/security benefits that come from having each app in its own classloader.

Getting "javax.servlet.ServletException: java.lang.RuntimeException: No ClassLoaders found for:" exception when receiving serialization object

I am trying to access set of Java class files from my web page. Serialized object is passed to the web application and the following error has thrown when receiving the serialized object in the web app.Previously i used java 1.5.At that time it was working fine. Now i moved to java 1.7.Now getting this exception
javax.servlet.ServletException: java.lang.RuntimeException: No ClassLoaders found for : classfile name.
All the class files are present in the /WEB_INF/classes directory. How do I solve this?
Finally i got the solution for the issue.modifying the parameter "UseJBossWebLoader" as true in the jboss configuration file. –

Categories

Resources