Ok. When I tried to setup Spring Aspect for Spring JDBC, I got Exception as in Aspect for Spring JDBC.
Now I changed code and config a bit and I do not see any exception. Still my aspect is not called.
Here is the configuration.
<bean name="com.application.dao.JDBCTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource">
<ref bean="gov.usda.fsa.pscao.clg.cops.dao.DataSource"/>
</property>
</bean>
<bean name="com.application.dao.NamedParameterJdbcTemplate" class="org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate">
<constructor-arg index="0">
<ref bean="com.application.dao.JDBCTemplate"/>
</constructor-arg>
</bean>
....
<context:component-scan base-package="com.application.spring.aspect"></context:component-scan>
<aop:aspectj-autoproxy proxy-target-class="true"/>
<bean name="sqlLoggingInterceptor" class="com.application.spring.aspect.SQLLoggingInterceptor" />
<aop:config>
<aop:aspect id="aspect4" ref="sqlLoggingInterceptor">
<aop:pointcut expression="execution(* org.springframework.jdbc.core.JdbcOperations.*(String, ..))" id="pointcut4" />
<aop:around pointcut-ref="pointcut4" method="profile" />
</aop:aspect>
</aop:config>
Aspect implementation:
#Aspect
#Component
public class SQLLoggingInterceptor {
public SQLLoggingInterceptor() {
System.out.println("SQLLoggingInterceptor created...");
}
public Object profile(ProceedingJoinPoint pjp) throws Throwable {
//do logging
}
}
My dependencies are (Spring version 3.2.8):
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.7.2</version>
</dependency>
<dependency>
<groupId>aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.5.3</version>
</dependency>
And, JDBCtemplate is invoked like this:
NamedParameterJdbcTemplate jdbcTemplate;
jdbcTemplate.queryForList(SQL_STRING, parametersMap);
Considering the fact NamedParameterJdbcTemplate wrapper for JdbcOperations, I assume whenever I execute query like above, it should be able to invoke aspect. But the aspect is not called. Do I miss something here ? I would greatly appreciate any inputs or comments. Thanks in advance.
Related
My Spring application was using JPA transaction manager but for some situations I would like to use JTA transaction manager. Therefore I updated Spring config to something like that:
<beans>
<!-- Old config -->
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<!-- ...-->
<property name="jpaPropertyMap" ref="jpaPropertyMap"/>
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean>
<tx:annotation-driven proxy-target-class="true"/>
<!-- ...-->
<!-- Updated config-->
<util:map id="jpaPropertyMap" key-type="java.lang.String">
<!-- ... ->
<entry key="javax.persistence.transactionType" value="jta"/>
<entry key="hibernate.transaction.jta.platform" value="Atomikos"/>
</util:map>
<bean id="atomikosTransactionManager" class="com.atomikos.icatch.jta.UserTransactionManager" init-method="init" destroy-method="close">
<property name="forceShutdown" value="false"/>
</bean>
<bean id="atomikosUserTransaction" class="com.atomikos.icatch.jta.UserTransactionImp"/>
<bean id="jtaTransactionManager" class="org.springframework.transaction.jta.JtaTransactionManager">
<property name="transactionManager" ref="atomikosTransactionManager"/>
<property name="userTransaction" ref="atomikosUserTransaction"/>
</bean>
<!-- ...-->
</beans>
Now in Java code when I need several JPA transactions (to different databases) to act as one transaction I annotate the starting service method with #Transactional("jtaTransactionManager"), while for situation when I need a single transaction I use standard #Transactional annotation.
But I have observed that, because of the properties
<entry key="javax.persistence.transactionType" value="jta"/>
<entry key="hibernate.transaction.jta.platform" value="Atomikos"/>
even if I start a sigle JPA transaction, Hibernate internally is also using Atomikos transaction manager. Is it possible to have Hibernate use Atomikos for JTA transaction and to not use it for single JPA transactions?
I am using restTemplate for consuming json data from remote server, and then parsing the json in my java objects using jackson. I have added required message converters to my restTemplate by java code as:
List<HttpMessageConverter<?>> messageConverters = new ArrayList<HttpMessageConverter<?>>();
messageConverters.add(new FormHttpMessageConverter());
messageConverters.add(new StringHttpMessageConverter());
messageConverters.add(new MappingJacksonHttpMessageConverter());
restTemplate.setMessageConverters(messageConverters);
restTemplate.setRequestFactory(new CommonsClientHttpRequestFactory());
MyResponse myResponse = restTemplate.getForObject(caasUrl, MyResponse.class);
And my restTemplate is defined in my spring-config file as:
<bean id="restTemplate" class="org.springframework.web.client.RestTemplate">
<constructor-arg>
<bean class="org.springframework.http.client.HttpComponentsClientHttpRequestFactory">
<property name="readTimeout" value="630000" />
<property name="connectTimeout" value="30000" />
</bean>
</constructor-arg>
</bean>
And its working fine, now my question is how can we pass the list of message converters to restTemplate in xml configuration as I do not want to do the same by java code. any Help please
Try this...sample code below shows only 2 converters.
<property name="messageConverters">
<list>
<bean class="org.springframework.http.converter.FormHttpMessageConverter"/>
<bean class="org.springframework.http.converter.StringHttpMessageConverter"/>
......more....
</list>
</property>
I am trying to integrate spring with mybatis.I have done all the configuartions.
I have following versions :
Spring : 3.0.6
Mybatis : 3.0.6
mybatis-spring : 1.0.2
When I use above combination of jars ,at the startup of tomcat,it throws exception that SqlSessionFactoryBean classNotFound and when I actually check mybatis-spring-1.0.2 jar ,SqlSessionFactoryBean is actually not there.
Then I switched to mybatis-spring-1.2.0
Now on using this jar ,on server startup ,I get following error message :
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sqlSessionFactory' defined in ServletContext resource [/WEB-INF/applicationContext.xml]: Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [org.mybatis.spring.SqlSessionFactoryBean]: Constructor threw exception; nested exception is java.lang.NoClassDefFoundError: org/apache/ibatis/mapping/VendorDatabaseIdProvider
Configurations used are :
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<!-- org.springframework.jdbc.datasource.DriverManagerDataSource" -->
<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"/>
<property name="url" value="jdbc:oracle:thin:#10.10.10.10:1521:xe"/>
<property name="username" value="uname"/>
<property name="password" value="pwd"/>
</bean>
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="configLocation" value="/WEB-INF/mybatis-config.xml"/>
</bean>
<bean id="transactionDao" class="com.abc.daoImpl.TransactionDaoImpl">
<property name="sqlSessionFactory" ref="sqlSessionFactory" />
</bean>
Can you please let me know,what is probelm here .
Thanks in advance.
This class belongs to Ibatis and not MyBatis. Make sure that you have Ibatis as either direct dependency or transitive dependency.
I set it this way:
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="typeAliasesPackage" value="mx.com.dctechnology.model"/>
<property name="mapperLocations" value="classpath*:mx/com/dctechnology/dao/maps/*.xml" />
</bean>
<bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
<constructor-arg index="0" ref="sqlSessionFactory" />
</bean>
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="mx.com.dctechnology.dao" />
</bean>
Used in pom.xml:
<mybatis.version>3.4.1</mybatis.version>
<mybatis-spring.version>1.3.0</mybatis-spring.version>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>${mybatis.version}</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>${mybatis-spring.version}</version>
</dependency>
I have been spending the week attempting to integrate JPA / ServiceMix 4.5.1 / camel-jpa 2.10.4 / Blueprint together. I'm currently using OpenJPA, but am not tied to it. The version of aries jpa used by servicemix is 0.3.0.
The stack trace I cannot get past is:
org.osgi.service.blueprint.container.ComponentDefinitionException: Error when instanciating bean workoutEntity of class class [...].WorkoutEntity
at org.apache.aries.blueprint.container.BeanRecipe.getInstance(BeanRecipe.java:271)[10:org.apache.aries.blueprint:0.3.2]
at org.apache.aries.blueprint.container.BeanRecipe.internalCreate(BeanRecipe.java:708)[10:org.apache.aries.blueprint:0.3.2]
at org.apache.aries.blueprint.di.AbstractRecipe.create(AbstractRecipe.java:64)[10:org.apache.aries.blueprint:0.3.2]
at org.apache.aries.blueprint.di.RefRecipe.internalCreate(RefRecipe.java:60)[10:org.apache.aries.blueprint:0.3.2]
at org.apache.aries.blueprint.di.AbstractRecipe.create(AbstractRecipe.java:64)[10:org.apache.aries.blueprint:0.3.2]
at org.apache.aries.blueprint.container.BlueprintRepository.createInstances(BlueprintRepository.java:219)[10:org.apache.aries.blueprint:0.3.2]
[...]
Caused by: <openjpa-2.2.0-r422266:1244990 nonfatal general error> org.apache.openjpa.persistence.PersistenceException: [javax.sql.DataSource]
at org.apache.openjpa.kernel.AbstractBrokerFactory.newBroker(AbstractBrokerFactory.java:218)
at org.apache.openjpa.kernel.DelegatingBrokerFactory.newBroker(DelegatingBrokerFactory.java:156)
at org.apache.openjpa.persistence.EntityManagerFactoryImpl.createEntityManager(EntityManagerFactoryImpl.java:227)
[...]
Caused by: java.lang.IllegalArgumentException: [javax.sql.DataSource]
at org.apache.aries.jndi.services.ServiceHelper.proxyPriviledged(ServiceHelper.java:348)
at org.apache.aries.jndi.services.ServiceHelper.access$700(ServiceHelper.java:65)
at org.apache.aries.jndi.services.ServiceHelper$1.run(ServiceHelper.java:285)
at java.security.AccessController.doPrivileged(Native Method)[:1.6.0_43]
[...]
I've attempted several variations. Here is my current configuration:
persistence.xml:
<persistence-unit name="customer1" transaction-type="JTA">
<provider>org.apache.openjpa.persistence.PersistenceProviderImpl</provider>
<jta-data-source>osgi:service/javax.sql.DataSource/(osgi.jndi.service.name=jdbc/prototypedb)</jta-data-source>
<class>...</class>
</persistence-unit>
camel-context.xml
<service id="PrototypeDB" interface="javax.sql.DataSource">
<service-properties>
<entry key="osgi.jndi.service.name" value="jdbc/prototypedb"/>
</service-properties>
<bean class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/prototype"/>
<property name="username" value="root"/>
<property name="password" value="..."/>
</bean>
</service>
<service ref="workoutEntity" interface="..."/>
<bean id="workoutEntity" class="...">
<jpa:unit index="0" unitname="customer1" />
<tx:transaction method="*" value="Required"/>
</bean>
Entity Bean (written in groovy)
#Entity
#Table(name='customer1')
#Slf4j
class WorkoutEntity implements IWorkoutEntity{
private EntityManager entityManager
WorkoutEntity(final EntityManagerFactory entityManagerFactory) {
this.entityManager = entityManagerFactory.createEntityManager()
}
#Handler
void create( #Body final String input) {
// ...
}
}
I've attempted multiple different implementations of a DataSource, including the BasicDataSource, org.springframework.jdbc.datasource.SimpleDriverDataSource, and com.mysql.jdbc.jdbc2.optional.MysqlDataSource. All cause the IllegalArgumentException.
I've also attempted to forego using JNDI and instead define the data source directly in the persistence.xml. This causes ClassNotFoundException in the OpenJPA bundle, as it is not importing the mysql driver. I'd prefer to define this in my camel-context.xml and would prefer to not re-bundle the OpenJPA jar.
You probably also need the aries JNDI features installed. This helps to call OSGi services via JNDI lookups. This should be the missing piece.
I have a core library that has an interface that I want to expose as an OSGI service in Fuse ESB (Apache ServiceMix and Karaf). The goal is to allow other bundles to use it. The service uses JPA (OpenJPA) and Spring. The following is the interface:
public interface PatientService {
public Patient find(Integer id);
}
and the class:
#Repository
public class PatientServiceJpaImpl implements PatientService {
#PersistenceContext(unitName="psu")
private EntityManager entityManager;
#Override
public Patient find(Integer id) {
return entityManager.find(Patient.class, id);
}
}
The following is an abbreviated META-INF/spring/beans.xml:
<beans xmlns="http://www.springframework.org/schema/beans" ...>
<context:annotation-config />
<context:component-scan base-package="..." />
<bean id="txManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="emf" />
</bean>
<bean id="emf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceUnitName" value="psu" />
<property name="jpaVendorAdapter" ref="jpaAdapter" />
<property name="dataSource" ref="dataSource" />
</bean>
<bean id="jpaAdapter" class="org.springframework.orm.jpa.vendor.OpenJpaVendorAdapter" />
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<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 class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"/>
<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />
</beans>
And the META-INF/persistence.xml (also abbreviated):
<persistence xmlns="http://java.sun.com/xml/ns/persistence" ...>
<persistence-unit name="psu" transaction-type="RESOURCE_LOCAL">
<class>...</class>
</persistence>
In a non-OSGi environment, everything works great. It uses the felix maven-bundle-plugin, so to create the OSGi service, I added the following OSGI-INF/blueprint/osgi-context.xml:
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.osgi.org/xmlns/blueprint/v1.0.0
http://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd">
<bean id="patientService" class="com.test.service.PatientServiceJpaImpl" />
<service id="osgiPatientService" ref="patientService" interface="com.test.service.PatientService" />
</blueprint>
The bundle is deployed successfully and the service is registered. The problem is that when the PatientService is referenced from another bundle, the entity manager has not been injected, thus throwing a NullPointerException in the find(Integer id) method. The following is a snippet of the consumer's META-INF/spring/consumer-context.xml:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:jaxws="http://cxf.apache.org/jaxws"
xmlns:osgi="http://www.springframework.org/schema/osgi"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://cxf.apache.org/jaxws
http://cxf.apache.org/schemas/jaxws.xsd
http://www.springframework.org/schema/osgi
http://www.springframework.org/schema/osgi/spring-osgi.xsd">
<bean id="patientServiceImpl" class="com.test.ws.PatientWebServiceImpl" >
<property name="patientService">
<osgi:reference interface="com.test.service.PatientService"/>
</property>
</bean>
...
</beans>
Just to be clear, the PatientService is injected in the consumer bundle, but the entity manager is not injected in the provider bundle. Also, it does not appear to be an issue with the persistence unit due to the following log output when starting the original service:
125 psu TRACE [SpringOsgiExtenderThread-14] openjpa.Runtime - org.apache.openjpa.persistence.PersistenceProviderImpl#24a5031d creating container org.apache.openjpa.persistence.EntityManagerFactoryImpl#4d6f77b6 for PU psu.
To get an idea what is going on, I logged the the object memory reference and stack trace in the constructor of the PatientServiceJpaImpl class. The constructor was called twice (creating two different objects):
The first output appears to originate from the osgi container starting from org.apache.felix and more or less ending in org.apache.aries.blueprint.
The second output appears to originate from the spring framework starting from org.springframework.osgi and more or less ending in org.springframework.beans.BeanUtils.
When the consumer service is called, the reference it has is to the blueprint instantiated object, which does not have an injected entity manager. Also from the logs, the persistence unit is instantiated after the blueprint instantiation of the PatientServiceJpaImpl object.
I have searched and tinkered with this issue for quite a while and I've run out of ideas. The irony is that it actually worked at one point, but I had made so many changes to get it to work that it was a rats nest that I was not able to back out of successfully.
Why is the persistence context not injected in the blueprint managed object? Any ideas will be appreciated. Thanks.
I'm not sure if this is going to work, cause you are mixing spring with blueprint. I have a working application based only on blueprint and I'm quite happy. For your use-case I'd suggest using blueprint at least for your JPA part. You still can use spring-dm for using the jpa classes as services.
<blueprint default-activation="eager"
xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jpa="http://aries.apache.org/xmlns/jpa/v1.0.0" xmlns:tx="http://aries.apache.org/xmlns/transactions/v1.0.0">
<bean id="patientService" class="com.test.service.PatientServiceJpaImpl" >
<jpa:context property="em" unitname="dn1" />
<tx:transaction method="*" value="Required" />
</bean>
<service id="osgiPatientService" ref="patientService" interface="com.test.service.PatientService" />
</blueprint>
Your PatientServiceJPAImpl I would change to not contain any annotations.
public class PatientServiceJpaImpl implements PatientService {
protected EntityManager em;
#Override
public Patient find(Integer id) {
return em.find(Patient.class, id);
}
}
A good way to deal with this would be to use Gemini JPA. With Gemini JPA, your JPA bundle would automatically expose an EntityManagerFactory OSGi service, based on the configurations in your persistence.xml. Thus, in the JPA client bundle, the blueprint just needs to import this service with a filter condition specifying the persistence unit name.
Here's a small implementation on those lines: mvc-osgi
If the EMF service doesn't work for you, you can use the EntityManagerFactoryBuilder service exposed by the Gemini JPA bundle to manually create the EMF. This would require calling the "createEntityManagerFactory".