GlassFish randomly selects wrong JCA ConnectionFactory for Injection - java

I am in the process of writing a JCA Resource Adapter for FTP and SFTP. As my goal is to be able to use one protocol completely independent from the other, I have two different ManagedConnectionFactory classes, one for each protocol. Both have different ConnectionDefinition annotations; the Glassfish domain.xml contains a resource definition for the FTP Adapter but not for the SFTP Adapter. Now, when I inject the FTPConnectionFactory into an EJB, I sometimes get an InjectionException as WELD tries to inject the SFTPConnectionFactory instead (this is of course consistent during a run of the appserver; I either consistently get the right or the wrong one). Removing the ConnectionDefinition annotation for the SFTP adapter seems to fix the problem.
So, Questions:
How can I fix this and make Glassfish inject the correct class? Can this be caused by a problem in my code or is this a Glassfish issue?
According to the spec it is legal for a RA to have multiple ConnectionDefinition annotations, as well as multiple instances of a class implementing ManagedConnectionFactory; but I couldn't find any information about having multiple different classes implementing ManagedConnectionFactory inside of the same Resource Adapter. Glassfish clearly seems to have a problem with it - is this explicitly allowed or disallowed somewhere?
The ConnectionDefinition (with FTP replaced by SFTP for the SFTP case):
#ConnectionDefinition(connectionFactory = FTPConnectionFactory.class,
connectionFactoryImpl = FTPConnectionFactoryImpl.class,
connection = FTPConnection.class, connectionImpl = FTPConnectionImpl.class)
The FTP and SFTP Factory and ManagedConnection classes share common ancestors but are not directly related - but this doesn't seem to matter as completely separating the implementations makes no difference.
The domain.xml snippet:
<resource-adapter-config resource-adapter-name="ftpconnector" thread-pool-ids="thread-pool-1" />
<connector-connection-pool name="jca/ftpConnectorPool"
resource-adapter-name="ftpconnector"
connection-definition-name="foo.bar.ftp.FTPConnection"
transaction-support="NoTransaction" match-connections="false" />
<connector-resource pool-name="jca/ftpConnectorPool" jndi-name="jca/ftpConnector" />
And the injected field:
#Resource(lookup = "jca/ftpConnector")
private FTPConnectionFactory ftpConnectionFactory;

TL;DR: This was caused by an incorrectly configured Connection Pool, where connection-definition-name does not point to a class implementing ConnectionFactory. The observed behaviour is IMO a bug and has been reported here.
While trying to reproduce this issue with Adam Biens connectorz Filesystem Resource Adapter (by adding a second set of classes and another connection definition), I found I could only reproduce the behaviour if the connector-connection-pool in the domain.xml is incorrectly defined: If I changed the connection-definition-name to point to a nonexistent class, Glassfish would randomly take one of the two defined connectors. Doublechecking my Connection Pool, I found out that I mistakenly used the Connection class instead of the ConnectionFactory class in the xml. So when the attribute does not point to a class implementing the ConnectionFactory interface, Glassfish seems to randomly choose any class from the Resource Adapter which implements ConnectionFactory, without even printing an error message.

Related

Registering DirectChannelMetrics as a JMX Bean programmatically

I have a Spring integration application with several FileTailingMessageProducers and DirectMessageChannels created programmatically -- i.e. not through XML configuration, but within a ApplicationListener<ContextRefreshedEvent>. Now I would like to monitor the message channels using JMX. I guess I will have to add them using my integrationMBeanExporter.
This is what I tried:
DirectChannelMetrics directChannelMetrics = new DirectChannelMetrics(tailedLines, "tailedLines");
integrationMBeanExporter.getServer().registerMBean(directChannelMetrics, new ObjectName("d:foo=foo"));
Yet I am getting the following Exception:
javax.management.NotCompliantMBeanException: MBean class org.springframework.integration.monitor.DirectChannelMetrics does not implement DynamicMBean, and neither follows the Standard MBean conventions
It is surprising to me, that the DirectChannelMetrics does not fulfill JMX requirements, since when I look into my application with jvisualvm I can see other beans of this type registered without problems.
Any ideas?
From one side MBeanExporter does this on the matter:
return new StandardMBean(bean, ((Class<Object>) ifc));
Before registering bean as an MBean.
From other side I think your logic smells a bit. It looks abnormal to create MessageChannels at runtime. Especially those which are for the JMX export.
I can agree about dynamic FileTailingMessageProducers, but seems for me we can avoid dynamic channels with refactored logic for the predefined channels.
You could leverage Spring's MBeanExport.registerManagedResource(directChannelMetrics, new ObjectName("d:foo=foo")). Spring will generate a management interface for the instance of DirectChannelMetric class. But DirectChannelMetric class needs either to implement the Mbean/MXBean interface or to match current MBeanInfoAssembler expectations(be marked with the #ManagedResource annotation in the case of MetadataMBeanInfoAssembler or implements one of specified interfaces in the case of InterfaceBasedMBeanInfoAssembler etc).

What means this JMS configuration into a Spring application?

I am studying how Spring framework handle JMS and I have the following doubt related this question founded on my study material.
Consider the following JMS configuration defined into a Spring application:
<jms:listener-container connetionFactory="connectionFactory">
<jms:listener-destination="order.queue" ref="orderListener" method="order" />
</jms:listener-container>
What exactly does this configuration?
Now I know that a JMS connection is tipically obtained from a factory, so I think that it is configuring the factory that give me my JMS connection (is it right?)
But what exactly specify this line?:
<jms:listener-destination="order.queue" ref="orderListener" method="order" />
Tnx
That would be a Message-driven Bean-like in the plain Java EE world. Have a look here. By the way, the attribute is destination="queue.name"; there is no such a thing like <jms:listener-destination="order.queue"...
destination: The destination name for this listener (in other words: the queue where the listener will "listen" to; named as destination in newer versions of Spring)
ref: The bean name of the handler (see next point)
method: The name of the handler method to invoke. If the ref points to a MessageListener or Spring SessionAwareMessageListener, this attribute may be omitted (this is why the latter two must implements the onMessage method, and by convention this will be called)

EJB2 xdoclet #ejb.ejb-ref in session bean pointing to itself

I'm working now on migration from EJB 2.0 to 3.0.
Old session beans used xdoclets to configure some stuff.
I can understand almost all of them, but there is one thing that is bothering me.
Why do someone use #ejb.ejb-ref in way like in code below.
/**
* #ejb:bean name="SomeBean"
* local-jndi-name="com/my/jndi/SomeBean"
* view-type="local" type="Stateless"
*
* #ejb.ejb-ref ejb-name="SomeBean"
* view-type="local"
*
* ..some more stuff here
*/
public class SomeBean implements SessionBean {
// class body here
}
There is few more #tags in this xdoclet including some for configuring weblogic (#weblogic).
Is there some reason we may want to add reference to bean itself?
Second question, is this config still needed in ejb3?
I have this feeling that I read somewhere that this #weblogic tags may sometimes need to use this kind of reference but I just cannot find it one more time. Is it true?
#EDIT
After talk with one of the authors of such classes, i find out that such self-reference may be used when one of bean methods calls second method (which may have to require new transaction) by using reference to instance of class it's owns.
After upgrade it can be replaced by something like this below.
#Stateless
public class SomeBean implements IBeanLocal {
#EJB
IBeanLocal someBean;
// class body here
}
My confusion was mainly caused by some unnecessary uses of this kind of self-reference.
As pointed by Steve C, probably someone wasn't sure how to use this xdoclet feature.
First of all, the "local" view types imply that you're looking at EJB 2.1 code (not 2.0).
I agree that the #ejb.ejb-ref tag is curious. It would only be useful if it was using JNDI somewhere to look up another instance of the same type of session bean. And even then it's redundant because the ejb home objects are available in the bean's EJBContext object.
It's quite possible the original authors did not know what the ejb-ref was for. There was a lot of that going around at the time.
If there was an ejb-ref to another type of bean, then you would typically see a corresponding #weblogic.ejb-local-reference-description or #weblogic.ejb-reference-description which is used to generate the JNDI mapping information in the weblogic.xml file, linked by the ejb-name.
In any event, you would replace any of these lookup references with instance variables marked up with #EJB.
The complete xdoclet documentation (and source) is still available at (http://xdoclet.sourceforge.net/xdoclet/index.html), FWIW.

JMX MXBean Attributes all UNDEFINED - Spring 3.0.x/Tomcat 6.0

I've been trying to get a sample JMX MXBean working in a Spring-configured webapp, but any basic attributes on the MXBean are coming up as UNDEFINED when I connect with jconsole.
Java interface/classes:
public interface IJmxBean { // marker interface for spring config, see below
}
public interface MgmtMXBean { // lexical convention for MXBeans - mgmt interface
public int getAttribute();
}
public class Mgmt implements IJmxBean, MgmtMXBean { // actual JMX bean
private IServiceBean serviceBean; // service bean injected by Spring
private int attribute = 0;
#Override
public int getAttribute() {
if(serviceBean != null) {
attribute = serviceBean.getRequestedAttribute();
}
return attribute;
}
public void setServiceBean(IServiceBean serviceBean) {
this.serviceBean = serviceBean;
}
}
Spring JMX config:
<beans>
<context:component-scan base-package="...">
<context:include-filter type="assignable" expression="...IJmxBean" />
</context:component-scan>
<context:mbean-export />
</beans>
Here's what I know so far:
The element is correctly instantiating a bean named "mgmt". I've got logging in a zero-argument public constructor that indicates it gets constructed.
is correctly automatically detecting and registering the MgmtMXBean interface with my Tomcat 6.0 container. I can connect to the MBeanServer in Tomcat with jconsole and drill down to the Mgmt MXBean.
When examining the MXBean, "Attribute" is always listed as UNDEFINED, but jconsole can tell the correct type of the attribute. Further, hitting "Refresh" in jconsole does not actually invoke the getter method of "Attribute"- I have logging in the getter method to indicate if it is being invoked (similar to the constructor logging that works) and I see nothing in the logs.
At this point I'm not sure what I'm doing wrong. I've tried a number of things, including constructing an explicit Spring MBeanExporter instance and registering the MXBean by hand, but it either results in the MBean/MXBean not getting registered with Tomcat's MBean server or an Attribute value of UNDEFINED.
For various reasons, I'd prefer not to have to use Spring's #ManagedResource/#ManagedAttribute annotations.
Is there something that I'm missing in the Spring docs or MBean/MXBean specs?
ISSUE RESOLVED: Thanks to prompting by Jon Stevens (above), I went back and re-examined my code and Spring configuration files:
Throwing an exception in the getAttribute() method is a sure way to get "Unavailable" to show up as the attribute's value in JConsole. In my case:
The Spring JMX config file I was using was lacking the default-autowire="" attribute on the root <beans> element;
The code presented above checks to see if serviceBean != null. Apparently I write better code on stackoverflow.com than in my test code, since my test code wasn't checking for that. Nor did I have implements InitializingBean or #PostConstruct to check for serviceBean != null like I normally do on almost all the other beans I use;
The code invoking the service bean was before the logging, so I never saw any log messages about getter methods being entered;
JConsole doesn't report when attribute methods throw exceptions;
The NPE did not show up in the Tomcat logs.
Once I resolved the issue with serviceBean == null, everything worked perfectly. Regardless, +1 to Jon for providing a working demo, since there are literally 50 different ways to configure MBeans/MXBeans within Spring.
I've recently built a sample Spring based webapp that very cleanly enables JMX for latest versions of Spring, Hibernate and Ehcache.
It has examples for both EntityManager based access and DAO access (including transactions!). It also shows how to do annotation based injection in order to negate having to use Spring's xml config for beans. There is even a SpringMVC based example servlet using annotations. Basically, this is a Spring based version of a fairly powerful application server running on top of any servlet engine.
It isn't documented yet, but I'll get to that soon. Take a look at the configuration files and source code and it should be pretty clear.
The motivation behind this is that I got tired of all of the crazy blog posts with 50 different ways to set things up and finally made a single simple source that people can work from. It is up on github so feel free to fork the project and do whatever you want with it.
https://github.com/lookfirst/fallback

JNDI ClassCastException

I am attempting to use JNDI with a custom DataSource called CEDataSource. From my understanding for this to work I would have to create a custom factory as well.
So I created a custom factory that would return the CEDataSource object but now when I attempt to use this in Java with
Context initCtx = new InitialContext();
Context envCtx = (Context) initCtx.lookup("java:comp/env");
// Look up our data source
CEDataSource ds = (CEDataSource)envCtx.lookup("jdbc/cePu");
I get the exception ClassCastException
"CEDataSource cannot be mapped to CEDataSource". I added the CEDataSource and the CEDataSourceFactory to the TOMCAT/lib folder as well as referenced this same jar on my deployed application.
Any help would be greatly appreciated on why this possible error may occur. Thanks
"CEDataSource cannot be mapped to CEDataSource" seems to point to the fact that it's not the same "CEDataSource" in both places.
What could be different is the classloader and this usually happens if you have the same jars/.class(es) in multiple locations.
Do you have multiple copies of your jar?
Try to have a single copy, maybe in the shared tomcat lib so it's loaded by the same classloader no matter from where you access it from.
It is actually not too difficult to start Tomcat under an Eclipse debug session (just put all the Bootstrap.jar in a project and add the System properties in the JVM parameters). II've done that many times, if only to dissect the bowels of that feline. Once this is done you can break on the class cast exception of the JNDI connection factory and you will then be able to see if your factory is called or not.
From what I remember Tomcat uses the DBCP DataSource. Actually repackaged under com.apache.tomcat.dbcp.dbcp.DataSource (IIRC).
So I would not be surprised if this is what you end up with as a result of your look-up.
With hindsight, I now realize I also forgot to mention that if any underlying class (for instance a JDBC driver) needed to create the instance of your CEDataSource is missing you also get this ClassCastException. Fair enough, but you always focus on the class itself and not on the other jars...
CEDataSource ds = (CEDataSource)envCtx.lookup("jdbc/cePu");
The lookup you are doing on jdbc/cePu is not of class type CEDataSource , it belongs to some other class type, that is why you are getting class cast exception. if you could show me the configuration for jdbc/cePu that would be helpful.

Categories

Resources