Issue with JMS + AOP + JNDI Resources - spring

Hi and happy new year
I'm working on a project which need to implement jms, aop and some jndi resources.
So far, the project works fine when there are only jms and jndi but when i activated aop, i had some troubles.. here is the configuration :
<!-- JMS implementation -->
<bean id="jmsRefConnectionFactory.activemq" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="java:comp/env/jms/activeMQConnectionFactory" />
<property name="lookupOnStartup" value="false" />
<property name="proxyInterface" value="javax.jms.QueueConnectionFactory" />
</bean>
<bean id="jmsRefQueue.activemq" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="java:comp/env/jms/activeMQQueue" />
<property name="lookupOnStartup" value="false" />
<property name="proxyInterface" value="javax.jms.Queue" />
</bean>
<bean id="jmsConnectionFactory.activemq" class="org.springframework.jms.connection.SingleConnectionFactory">
<constructor-arg ref="jmsRefConnectionFactory.activemq" />
</bean>
<bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
<property name="connectionFactory" ref="jmsConnectionFactory.activemq" />
<property name="defaultDestination" ref="jmsRefQueue.activemq" />
<property name="destinationResolver" ref="jmsDestinationResolver.amq" />
<property name="sessionTransacted" value="true" />
<property name="sessionAcknowledgeMode" value="#{T(javax.jms.Session).CLIENT_ACKNOWLEDGE}" />
</bean>
<bean id="transactionManager" class="org.springframework.jms.connection.JmsTransactionManager">
<property name="connectionFactory" ref="jmsRefConnectionFactory.activemq" />
</bean>
<bean id="jmsDestinationResolver.amq"
class="org.springframework.jms.support.destination.DynamicDestinationResolver" />
When I start the application, I get this error :
Caused by: org.springframework.aop.AopInvocationException: AOP configuration seems to be invalid: tried calling method [public abstract javax.jms.Connection javax.jms.ConnectionFactory.createConnection() throws javax.jms.JMSException] on target [org.apache.activemq.ActiveMQConnectionFactory#239f 6]; nested exception is java.lang.IllegalArgumentException: object is not an instance of declaring class
Context.xml content :
<!-- APACHE MQ -->
<Resource name="jms/activeMQConnectionFactory" auth="Container"
type="org.apache.activemq.ActiveMQConnectionFactory" description="JMS Connection Factory"
factory="org.apache.activemq.jndi.JNDIReferenceFactory" HOST="localhost"
PORT="61616" CHAN="" TRAN="1" QMGR="MyQCF" />
<Resource name="jms/activeMQQueue" auth="Container"
type="org.apache.activemq.command.ActiveMQQueue" description="my Queue"
factory="org.apache.activemq.jndi.JNDIReferenceFactory" physicalName="userQueue" />
Web.xml content :
<resource-ref>
<res-ref-name>jms/activeMQConnectionFactory</res-ref-name>
<res-type>javax.jms.QueueConnectionFactory</res-type>
<res-auth>Container</res-auth>
<res-sharing-scope>Shareable</res-sharing-scope>
</resource-ref>
<resource-ref>
<res-ref-name>jms/activeMQQueue</res-ref-name>
<res-type>javax.jms.Queue</res-type>
<res-auth>Container</res-auth>
<res-sharing-scope>Shareable</res-sharing-scope>
</resource-ref>
This configuration is OK when aop is not activated but for some reasons, it doesn't work when aop is on..
Spring version : 3.1.2
I'm using activemq (5.7)

I found out what was the problem..
Turns out the aop was not even involved (at least not the configuration that i put). I had some jar in my tomcat server that was not taken for some reasons (i think it's about lib priority/ parent first/last)...
I changed the location and directly put into my project and it works now ! :)

Related

Why is my local JPA setup not honored if using an EntityManagerFactory from JNDI using Spring?

AuditingEntityListener correctly updates columns marked with #LastModifiedDate, #CreatedDate, #CreatedBy and #LastModifiedBy in dev mode (mvn jetty:run) when I use LocalContainerEntityManagerFactoryBean. However, when I activate prod profile and deploy in Wildfly 8, the columns are not updated.
I found on this forum post: "You will need to use one of Spring's EntityManagerFactoryBeans to setup the EntityManagerFactory" Is there any way to use AuditingEntityListener with <jee:jndi-lookup /> EntityManagerFactory?
Here is my applicationContext.xml
<beans profile="dev">
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${database.driver}" />
<property name="url" value="${database.url}" />
<property name="username" value="${database.username}" />
<property name="password" value="${database.password}" />
</bean>
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="persistenceXmlLocation" value="classpath:/META-INF/local-container-persistence.xml" />
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
</beans>
<beans profile="prod">
<jee:jndi-lookup id="dataSource" jndi-name="java:jboss/datasources/postgresql-datasource" lookup-on-startup="false" expected-type="javax.sql.DataSource" />
<jee:jndi-lookup id="entityManagerFactory" jndi-name="java:jboss/entity-manager-factory" lookup-on-startup="false" expected-type="javax.persistence.EntityManagerFactory" />
<tx:jta-transaction-manager />
</beans>
<jpa:repositories base-package="com.corp.repository" factory-class="com.corp.RespositoryFactoryBean" />
<jpa:auditing auditor-aware-ref="entityAuditorAware" />
<bean name="entityAuditorAware" class="com.corp.EntityAuditorAware" />
orm.xml
<?xml version="1.0" encoding="UTF-8"?>
<entity-mappings xmlns="http://java.sun.com/xml/ns/persistence/orm" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence/orm orm_2_0.xsd"
version="2.0">
<persistence-unit-metadata>
<persistence-unit-defaults>
<entity-listeners>
<entity-listener class="org.springframework.data.jpa.domain.support.AuditingEntityListener" />
</entity-listeners>
</persistence-unit-defaults>
</persistence-unit-metadata>
</entity-mappings>
tl;dr
Make sure the EntityManagerFactory you obtain from JNDI is configured to have the AuditingEntityListener applied to the persistence unit you obtain.
Details
In your dev profile, The EntityManagerFactory is created within your application and thus - by definition in the spec - considers the locally available orm.xml.
In you prod example you don't bootstrap an EntityManagerFactory locally but obtain a preconfigured one from your application server. Thus you have to make sure the EntityManagerFactory instance is configured as you expected in the application server in the first place.

Spring factory-bean with property resolution

Is it possible to have property resolution on the factory-bean field of a Spring bean declaration?
Example:
<bean factory-bean="$APP{some.factory.bean}" factory-method="...">
Spring version: 3.2.4
Adding a PropertyPlaceholderConfigurer to your spring context should work:
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:yourfile.properties</value>
</list>
</property>
<property name="ignoreResourceNotFound" value="false" />
<property name="ignoreUnresolvablePlaceholders" value="false" />
</bean>
You can declare your propertyName in the file and then use it like:
<bean factory-bean="${propertyName}" factory-method="...">
Just encountered the same issue (using Spring 4.2.0). It seems that property resolution for factory beans does not work despite what they say in SPR-12638. I've ended up using ProxyFactoryBean as a workaround.
The desired configuration, which does not work:
<!-- The bean to be created: factory type determined in runtime -->
<bean id="..." factory-bean="factory-${factory.type}" factory-method="..." />
<!-- Possible factories -->
<bean id="factory-A" class="..." />
<bean id="factory-B" class="..." />
<bean id="factory-C" class="..." />
The workaround that I've found:
<!-- The bean to be created: use factory proxy -->
<bean id="..." factory-bean="factory-proxy" factory-method="..." />
<!-- The factory proxy: real factory type determined in runtime -->
<bean id="factory-proxy" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="target" ref="factory-${factory-type}" />
</bean>
<!-- Possible factories -->
<bean id="factory-A" class="..." />
<bean id="factory-B" class="..." />
<bean id="factory-C" class="..." />
Enjoy :)

spring db2 jndi datasource - ClassCastException

I've been spending some time today trying to specify a websphere 6.1 db2 jndi data source in my spring mvc 3.0 application config. I've followed a guide a got at http://www.ibm.com/developerworks/websphere/techjournal/0609_alcott/0609_alcott.html.
When I do this....
web.xml
<resource-ref>
<res-ref-name>jdbc/reportingManagerDataSource</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
<res-sharing-scope>Shareable</res-sharing-scope>
</resource-ref>
<resource-ref>
<res-ref-name>jdbc/reportingManagerCustDbDataSource</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
<res-sharing-scope>Shareable</res-sharing-scope>
spring files
<bean id="ePosDataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="java:comp/env/jdbc/reportingManagerDataSource"/>
<property name="lookupOnStartup" value="false"/>
<property name="cache" value="true" />
<property name="proxyInterface" value="javax.sql.DataSource" />
</bean>
<jee:jndi-lookup id="ePosDataSource"
jndi-name="jdbc/reportingManagerDataSource"
cache="true"
resource-ref="true"
lookup-on-startup="false"
proxy-interface="javax.sql.DataSource"/>
<bean id="custDbDataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="java:comp/env/jdbc/reportingManagerCustDbDataSource"/>
<property name="lookupOnStartup" value="false"/>
<property name="cache" value="true" />
<property name="proxyInterface" value="javax.sql.DataSource" />
</bean>
<jee:jndi-lookup id="custDbDataSource"
jndi-name="jdbc/reportingManagerCustDbDataSource"
cache="true"
resource-ref="true"
lookup-on-startup="false"
proxy-interface="javax.sql.DataSource"/>
I get the error ...
org.springframework.jdbc.CannotGetJdbcConnectionException: Could not get JDBC Connection; nested exception is java.sql.SQLException: DSRA8101E: DataSource class cannot be used as one-phase: ClassCastException: com.ibm.db2.jcc.DB2XADataSource incompatible with javax.sql.ConnectionPoolDataSource
I have been frantically googling away to try and find a solution but have been unsuccessful. Can someone show me what is required to successfully set up my datasource please?
thanks

Spring resource

Problem: I want to make the below bean definitions (specified in aaplicationContext.xml) optional for "org.springframework.web.context.ContextLoaderListener". If i am not providing the "emsPropLocation" context parameter correctly, tomcat web container is not able to initialized properly and it is obvious reason. Is there any way to make it optional?
appicationContext.xml:
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="ignoreResourceNotFound" value="false"/>
<property name="location" value="file:/#{contextParameters.emsPropLocation}" />
</bean>
<!-- TIBCO Connection Factory Bean -->
<bean id="tibcoConnectionFactory" class="com.tibco.tibjms.TibjmsConnectionFactory">
<constructor-arg value="${emsServerURL}"/>
<property name="userName" value="${emsUserName}"/>
<property name="userPassword" value="${emsPassword}"/>
<property name="connAttemptCount" value="${connAttemptCount}"/>
<property name="connAttemptDelay" value="${connAttemptDelay}"/>
<property name="connAttemptTimeout" value="${connAttemptTimeout}"/>
<property name="reconnAttemptCount" value="${reconnAttemptCount}"/>
<property name="reconnAttemptDelay" value="${reconnAttemptDelay}"/>
<property name="reconnAttemptTimeout" value="${reconnAttemptTimeout}"/>
</bean>
<!-- bean id="tibcoUtil" class="com.nr.ns.upload.TibcoUtil" scope="singleton">
<constructor-arg value="true"/>
</bean-->
<bean id="jmsExceptionListener" class="com.nr.ns.upload.LogMsgExceptionListener"/>
<!-- Spring CachingConnectionFactory Bean -->
<bean id="connectionFactory" class="org.springframework.jms.connection.CachingConnectionFactory">
<constructor-arg ref="tibcoConnectionFactory"/>
<property name="reconnectOnException" value="${reconnectOnException}"/>
<property name="sessionCacheSize" value="${sessionCacheSize}"/>
<property name="exceptionListener" ref="jmsExceptionListener"/>
</bean>
<!-- JMSTemplate Bean -->
<bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
<constructor-arg ref="connectionFactory"/>
<property name="receiveTimeout" value="${receiveTimeout}"/>
<property name="deliveryMode" value="${deliveryMode}"/>
</bean>
We are keeping WAR file outside tomcat and to make it happen we have "app.xml" file inside TOMCAT_HOME/conf/Catalina/localhost.
app.xml:
<Context path="/app"
docBase="/abc/ccp/app.war"
reloadable="true"
unpackWAR="false">
<Parameter name="emsPropLocation"
value="/xyz/config/EMSServerConf.properties"
override="false"/>
</Context>
have a try to change the ignoreResourceNotFound property of your propertyConfigurer to true.
If contextParameters.emsPropLocation is not set, this will default to what is afer the colon.
<property name="location" value="file:/#{contextParameters.emsPropLocation:/xyz/config/EMSServerConf.properties}" />

spring eclipselink problem with IntegrityException

I try to use spring with eclipseLink and I've got an IntegrityException.
This is my configuration:
<?xml version="1.0" encoding="UTF-8"?>
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
<import resource="data-source.xml" />
<tx:annotation-driven mode="proxy"
transaction-manager="transactionManager" />
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"
p:entityManagerFactory-ref="entityManagerFactory" />
<!-- Entity manager -->
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="persistenceUnitName" value="unit1" />
<property name="loadTimeWeaver">
<bean class="org.springframework.instrument.classloading.SimpleLoadTimeWeaver"/>
</property>
<property name="jpaVendorAdapter">
<bean
class="org.springframework.orm.jpa.vendor.EclipseLinkJpaVendorAdapter">
<property name="databasePlatform" value="org.eclipse.persistence.platform.database.DerbyPlatform" />
<property name="showSql" value="true" />
<property name="generateDdl" value="true" />
</bean>
<!-- <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"> -->
<!-- <property name="databasePlatform" value="org.hibernate.dialect.DerbyDialect"
/> -->
<!-- <property name="showSql" value="true" /> -->
<!-- <property name="generateDdl" value="true" /> -->
<!-- </bean> -->
</property>
</bean>
<bean id="jpaTemplate" class="org.springframework.orm.jpa.JpaTemplate">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
and exactly exception is:
[EL Config]: 2011-06-09 00:15:24.061--ServerSession(2050312009)--Connection(473155160)--Thread(Thread[main,5,main])--Connected: jdbc:derby://localhost:1527/springhib;create=true
User: app
Database: Apache Derby Version: 10.6.2.1 - (999685)
Driver: Apache Derby Network Client JDBC Driver Version: 10.7.1.1 - (1040133)
[EL Severe]: 2011-06-09 00:15:24.127--ServerSession(2050312009)--Thread(Thread[main,5,main])--Local Exception Stack:
Exception [EclipseLink-0] (Eclipse Persistence Services - 2.2.0.v20110202-r8913): org.eclipse.persistence.exceptions.IntegrityException
Descriptor Exceptions:
Exception [EclipseLink-148] (Eclipse Persistence Services - 2.2.0.v20110202-r8913): org.eclipse.persistence.exceptions.DescriptorException
Exception Description: The container policy [CollectionContainerPolicy(class org.eclipse.persistence.indirection.IndirectSet)] is not compatible with transparent indirection.
Mapping: org.eclipse.persistence.mappings.ManyToManyMapping[comments]
Descriptor: RelationalDescriptor(pl.adaknet.hibspring.domain.ArtEntity --> [DatabaseTable(ARTENTITY)])
but i don't have this problem when I use another Vendor
org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter
any ideas?
Try to use this loadtimeweaver implementation:
package net.palesz.util;
import org.springframework.instrument.classloading.SimpleLoadTimeWeaver;
public class JpaAwareLoadTimeWeaver extends SimpleLoadTimeWeaver {
#Override
public ClassLoader getInstrumentableClassLoader() {
ClassLoader instrumentableClassLoader = super.getInstrumentableClassLoader();
if (instrumentableClassLoader.getClass().getName().endsWith("SimpleInstrumentableClassLoader")) {
return instrumentableClassLoader.getParent();
} else {
return instrumentableClassLoader;
}
}
}
Spring context.xml config:
<bean id="loadTimeWeaver" class="net.palesz.util.JpaAwareLoadTimeWeaver" />
An odd error because IndirectSet is valid. It seems to be a class loader issue, but I have not seen this in Spring before.
It could be related to your usage of loadTimeWeaver, so you could try removing that.
In what environment are you running Spring?
you have to use agent for dynamic weaving
-javaagent:spring-agent-2.5.6.jar
i had tried eclipseLink agent, but it didn't work.
more info about weaving for JPA on Spring:
http://docs.spring.io/spring/docs/3.0.0.M3/reference/html/ch14s06.html
if you would like run your code on tomcat:
http://docs.spring.io/spring/docs/3.0.0.M3/reference/html/ch14s06.html#orm-jpa-setup-lcemfb-tomcat

Resources