Wicket with Spring declarative transaction - spring

It is possible to use the Spring Framework's #Transactional support outside of a Spring container. In reference documentation is chapter about AspectJ aspect. I'm trying to use it in my wicket application, but with no positive result.
application-context.xml:
<tx:annotation-driven transaction-manager="transactionManager" mode="aspectj" />
<context:annotation-config />
<context:component-scan base-package="com.wicket.app"/>
<context:spring-configured />
<bean id="annotationTransactionAspect" factory-method="aspectOf"
class="org.springframework.transaction.aspectj.AnnotationTransactionAspect">
<property name="transactionManager" ref="transactionManager"></property>
</bean>
In my form class annotated by #Configurable, I have:
#Transactional
public void process(IFormSubmittingComponent submittingComponent) {
super.process(submittingComponent);
getDao().getEntityManager().flush();
}
Stack trace:
org.apache.openjpa.persistence.TransactionRequiredException: Can only perform operation while a transaction is active.

You might be able to get this working using AspectJ load-time-weaving, but that's a very complex solution for a simple problem.
If you need declarative transactions, then I suggest you move the transactional logic from the wicket component down into a Spring bean, and invoke the Spring bean from the wicket object. The Spring bean would have the transactional annotations, and would be proxied correctly by the Spring container.

I have no experience with Wicket. But is your 'form class' (the one that contains method annotated with #Transactional) Spring managed code? i.e. Who creates the instances of the class?
If it's not, that Spring will not provide #Transactional support (neither will #Autowired work, etc).

Related

Prevent Spring from meddling with CDI annotations even for factory created instances

I have a legacy product's JAR that contain Spring (4.3.8) managed classes. I need to integrate it with CDI (JavaEE 7).
I have an interface from the legacy JAR, that is implemented by a CDI bean. The CDI bean is requested from the CDI BeanManager and returned from a factory method. The factory method is registered inside Spring XML and works as expected.
The problem occurs, when a Spring bean of the legacy JAR depends on the implemented interface. Spring than injects the CDI implementation instance and scans the class it for known annotations, namingly #Inject. It then tries to resolve the dependency, which doesn't work since the dependency is not available to Spring.
I already tweaked context:property-placeholder excludes, but that changes nothing.
So how can I tell Spring to stop trying to inject something in my factory produced bean instance?
I finally was able to solve (work around) the problem. I had to remove all CDI-Annotations in the legacy JAR (by replacining them with their Spring counterparts), so spring would any longer work.
Then I added the following XML block to the applicationContext.xml of my CDI WAR:
<context:component-scan annotation-config="false" base-package="com.example">
</context:component-scan>
<bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor">
<property name="autowiredAnnotationTypes">
<set>
<value>org.springframework.beans.factory.annotation.Autowired</value>
<value>org.springframework.beans.factory.annotation.Value</value>
</set>
</property>
</bean>
<bean class="org.springframework.context.annotation.CommonAnnotationBeanPostProcessor" />
<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />
<bean class="org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor" />
<bean class="org.springframework.beans.factory.annotation.CustomAutowireConfigurer">
<property name="customQualifierTypes">
<set>
<value>org.springframework.beans.factory.annotation.Qualifier</value>
</set>
</property>
</bean>
Basically that drops the support for #Inject, etc. from Spring and leaves it where it belongs: CDI.
It's a bit easier.
AutowiredAnnotationBeanPostProcessor is already a bean, so you can configure it before Spring starts to scan with a ServletContextListener to exclude #Inject annotations. At least from Spring 4.1+, AutowiredAnnotationBeanPostProcessor has a method setAutowiredAnnotationTypes, e.g.:
#WebListener
public class ApplicationConfigListener implements ServletContextListener {
#Override
public void contextInitialized(ServletContextEvent event) {
ApplicationContext appCtx = WebApplicationContextUtils.getWebApplicationContext(event.getServletContext());
Set<Class<? extends Annotation>> autowiredAnnotationTypes = new LinkedHashSet<Class<? extends Annotation>>();
AutowiredAnnotationBeanPostProcessor bean = appCtx.getBean(AutowiredAnnotationBeanPostProcessor.class);
autowiredAnnotationTypes.add(Autowired.class);
autowiredAnnotationTypes.add(Value.class);
bean.setAutowiredAnnotationTypes(autowiredAnnotationTypes);
}
}
You could use a SpringBeanAutowiringInterceptor too.
This is explained here.

When does spring use AOP without Aspectj.jar?

I can use annotation #Transactional at the top of my service PersonServiceBean and config transactionManager like below. After that, my service can execute db operations under transaction control through AOP.
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
.........
</bean>
<tx:annotation-driven transaction-manager="txManager"/>
<bean id="personService" class="cn.itcast.service.impl.PersonServiceBean">
<property name="dataSource" ref="dataSource"/>
</bean>
But i didn't include aspectj.jar into my project. How does it work? I heard spring implements AOP through aspectj.
It doesn't use AspectJ by default, but uses proxies (either JDK interface proxies or CGLIB proxies). So, when you inject a transactional bean into another bean, what you get injected is in fact a proxy to your actual bean instance, which intercepts the method calls and starts/commits/rollbacks transactions.
More in the documentation, of course.

Spring does not autowire beans with JAX-WS webservice end points

I am trying to consume a JAX-WS webservice written by me. I always get nullPointerException for spring autowired annotated beans. However, everything works fine within serverSide over web, but accessing beans through JAX-WS webservice.
I have tried by extending SpringBeanAutowiringSupport, but still no luck. How can I do this.
regards, Rohit
I had no experience extending SpringBeanAutowiringSupport but had successfuly used this approach:
Annotate webService class such a way :
#Component("yourWebService")
#WebService(endpointInterface ="your.package.YourServicePort")
Create new spring-context xml for webService and define JAX-WS endpoint :
<jaxws:endpoint
id="yourServiceEndpoint"
implementor="#yourWebService"
address="${yourWebService.wsdl.url}"> //load url from properties file
</jaxws:endpoint>
I suppose you know how to use props in spring, but will explain just in case. You should also create yourWebService.properties file and define it in spring context to use this construction ${yourWebService.wsdl.url} :
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>yourWebService.properties</value>
</list>
</property>
Using this approach I had successfuly used JAX with Spring

Why is autowiring required? What is the explanation of the concept of autowiring?

Why is autowiring required? What is the explanation for the concept of autowiring?
#autowired annotation in Spring Framework.
Autowiring is not required, just convenient.
It means that if you have a property that requires an InterfaceA and a single bean has been declared in Spring that is of type InterfaceA, instead of using XML to manually "wire up" the relationship (setting a bean reference as a property of another), you can let Spring do the wiring for you.
This is a common question for the beginners. As the beans are injected using DI (setter injections, constructor injections), why do we need auto-wiring? Auto-wiring also doing the same thing, right?
The answer is, it saves you from writing more code.
If using an XML file, using autowire attribute saves you from writing the wiring code in the bean definition.
Please look at code below.
Configuration code without Auto-wiring:
<bean id="employee" class="com.Employee">
<property name="name" value="Dexter"></property>
</bean>
<bean id="employeeService" class="com.EmployeeService">
<property name="employee" ref="employee"></property>
</bean>
Configuration code with Auto-wiring:
<bean id="employee" class="com.Employee">
<property name="name" value="Dexter"></property>
</bean>
<bean id="employeeService" class="com.EmployeeService" autowire="byName" />
Note that we did not have to write anything to refer property of EmployeeService, i.e., Employee. But still it was injected. Autowiring makes the container to search the bean configurations and do the collaboration among beans, without the developer specifically mentioning these.
If we use annotation, even we don’t have to write anything in XML files, including this autoware="byName", etc. Simply #Autowired on bean's setter/field/constructor is sufficient.

Correct way to get transactions using Spring Data Neo4j's simple object/graph mapping?

I'm using the simple object/graph mapping in Spring Data Neo4j 2.0, where I perform persistence operations using the Spring Data repository framework. I'm working with the repositories rather than working with the Neo4jTemplate. I inject the repositories into my Spring Web MVC controllers, and the controllers call the repos directly. (No intermediate service layer--my operations are generally CRUDs and finder queries.)
When I do read operations, there are no issues. But when I do write operations, I get "NotInTransactionException". My understanding is that read ops in Neo4j don't require transactions, but write ops do.
What's the best way to get transactions into the picture here, assuming I want to stick with the simple OGM? I'm wanting to use #Transactional, but putting that on the various repository interfaces doesn't work. If I introduce an intermediate service tier in between the controllers and the repositories and then annotate the service beans with #Transactional, then it works, but I'm wondering whether there's a simpler way to do it. Without Spring Data, I'd typically have access to the DAO (repository) implementations, so I'd be able to annotate the concrete DAOs with #Transactional if I wanted to avoid a pass-through service tier. With Spring Data the repos are dynamically generated so that doesn't appear to be an option.
First, note that having transactional DAOs is not generally a good practice. But if you don't have a service layer, then let it be on the DAOs.
Then, you can enable declarative transactions. Here's how I did it:
First, define an annotation called #GraphTransactional:
#Retention(RetentionPolicy.RUNTIME)
#Transactional("neo4jTransactionManager")
public #interface GraphTransactional {
}
Update: spring-data-neo4j have added such an annotation, so you can reuse it instead of creating a new one: #Neo4jTransactional
Then, in applicationContext.xml, have the following (where neo4jdb is your EmbeddedGraphDatabase):
<bean id="neo4jTransactionManagerService"
class="org.neo4j.kernel.impl.transaction.SpringTransactionManager">
<constructor-arg ref="neo4jdb" />
</bean>
<bean id="neo4jUserTransactionService" class="org.neo4j.kernel.impl.transaction.UserTransactionImpl">
<constructor-arg ref="neo4jdb" />
</bean>
<bean id="neo4jTransactionManager"
class="org.springframework.transaction.jta.JtaTransactionManager">
<property name="transactionManager" ref="neo4jTransactionManagerService" />
<property name="userTransaction" ref="neo4jUserTransactionService" />
</bean>
<tx:annotation-driven transaction-manager="neo4jTransactionManager" />
Have in mind that if you use another transaction manager as well, you'd have to specify order="2" for this annotation-driven definition, and also have in mind that you won't have two-phase commit if you have one method that is declared to be both sql and neo4j transactional.

Resources