Spring transactions - Mixing #Transactional with <tx:advice> into a custom annotation - spring-transactions

My goal is to have some way of declaring my service classes as transactional. I dont want to leave it as an explicit declaration in spring configuration. Many times in past we have created new services and forgot to declare transactions around them. Hence my intention is that if i have something like #TransactionalService custom annotation, it should do the following :-
1. provides transactional support
2. declares some default rules for transactional support as spring currently provides as shown below. But unlike spring, i would like the below to be part of my #TransactionService annotation.
<tx:advice id="txAdvice" transaction-manager="txManager">
<tx:attributes>
<!-- all methods starting with 'get' are read-only -->
<tx:method name="get*" read-only="true"/>
<tx:method name="*"/>
Any advice would be valuable?

Sure, instead of creating a new annotation, you could just put your transactionnal services in the same package, and then your pointcut (only one for all you transactionnal services) will look like this :
<aop:config>
<aop:pointcut id="transactionnalServiceMethods" expression="execution(* x.y.transactionnalservice.*.*(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="transactionnalServiceMethods"/>
</aop:config>
The advice is the same as above :
<tx:advice id="txAdvice" transaction-manager="txManager">
<tx:attributes>
<!-- all methods starting with 'get' are read-only -->
<tx:method name="get*" read-only="true"/>
<tx:method name="*"/>
</tx:attributes>
</tx:advice>

Related

how to write class to do Database operation - spring integeration

i have a code
<int-jpa:updating-outbound-gateway
request-channel="nativeQlChannel" auto-startup="true"
native-query="update Transactions t set t.transaction_Status = :transactionStatus where t.bank_Reference_Number = :bankReferenceNumber "
entity-manager="entityManager" persist-mode="PERSIST" reply-channel="nativeQlChannelOne"
use-payload-as-parameter-source="false">
it works fine , but as i need to execute insert operation on more than one table , and i am not able to do that by this configuration ,
how can i write code using spring integration JPA class like JpaOutboundGatewayFactoryBean , or any other so that i can perform DB operation in my java code.
First of all it isn't JPA responsibility to worry about "more than one table".
It operates only with the entities as a high level abstraction.
Although yes, you can map your entity to several tables. Plus there is cascade insert when you have dependencies.
In addition that component supports native-query/native-query if you need more graceful control for your DB operation.
As for Java configuration correct: you should use JpaOutboundGatewayFactoryBean #Bean together with the #ServiceActivator to reach similar behavior.
You can find more samples in the Reference Manual.
i am able to fix it by using
ExpressionEvaluatingParameterSourceFactory
ExpressionEvaluatingParameterSourceFactory paramFactory=new ExpressionEvaluatingParameterSourceFactory() ;
paramFactory.setParameters(paramList);
but i got exception
WARN - o.s.i.e.ExpressionUtils: Creating EvaluationContext with no beanFactory
java.lang.RuntimeException: No beanfactory
although it is not stopping any functionality . so i just ignored it.

How to set payload as constructor-arg value in service-activator

I've started with SI and kind of stuck right now as we want to use SI in one of our existing project avoiding changes where we can.
A bean which we would be using as a service activator accepts an constructor argument of a java object.
that object is in the payload but then I'm unable to set it using inner bean usage of service-activator
<service-activator input-channel="ADMIN_TEST_CONNECTION" method="testConnection">
<beans:bean class="mypackage.request.AdminRequestProcessor">
<beans:constructor-arg value="payload"/>
</beans:bean>
</service-activator>
it's complaining about Could not convert argument value of type [java.lang.String] to required type.
Please help in how to access payload and set it as an constructor argument.
If I go via non- constructor arg route and change existing java object then it works with this call in the service activator
expression="#bean.testConnection(payload)"/>
but I don't wish you to change the existing java code until there is no other way.
I think you don't have choice unless change something or add code around existing.
Service-Activator performs its functionality against each incoming message in the input-channel. And that functionality is exactly method invocation where Message is used as a context for method arguments.
Not sure what you are going to do with that payload, but that doesn't look correct to use statefull object like your AdminRequestProcessor. Just don't forget that you may have many incoming message, but service-activator should be consistent.
Plus don't forget that <beans:bean> is singleton, so your AdminRequestProcessor is instantiated only once.
Looking to your sample I'd suggest something like this:
expression="new AdminRequestProcessor(payload).testConnection()"/>
If you really don't want to change anything in your code.
Everything rest you can find in the Reference Manual.

Spring Integration jdbc stored procedure custom rowmapper

I am newbie to Spring Integration and am using Spring 4.2.4.
I am trying to invoke stored procedure with jdbc:stored-proc-outbound-gateway. i am already using spring jdbc.
Stored procedure is returning cursor and am using customRowMapper like below
new SqlOutParameter(A_RC, OracleTypes.CURSOR, null, new MyCustomDataExtractor())
MyCustomDataExtractor implements SqlReturnType and it returns custom object.
Now the question is how can I achieve this in SI jdbc stored proc.piece of my code here..
...
<int-jdbc:sql-parameter-definition name="A_RC" type="#{T(oracle.jdbc.OracleTypes).CURSOR}" direction="OUT"/>
...
<int-jdbc:returning-resultset name="A_RC" row-mapper="a.b.c.MyCustomDataExtractor"/>
...
Spring expect this as a row mapper. should I use any transformer here? Please advice.
Note : I have to return multiple resultset.
Actually with the CURSOR type you are good to go with just a returning-resultset and RowMapper implementation.
With that you don't need to worry about any SqlReturnType and just map the row to your domain object directly.
I'm even sure you can rework your MyCustomDataExtractor to the RowMapper contract.
Note: with returning-resultset defintion you don't need to
specify the sql-parameter-definition for the same OUT param. The component identifies them correctly as a OutParameter.
And, yes you can have several returning-resultset for CURSOR parameters.
I added the return-type in the sql-parameter-definition and removed returning-resultset.
<int-jdbc:sql-parameter-definition name="A_RC" type="#{T(oracle.jdbc.OracleTypes).CURSOR}" direction="OUT" return-type="ed"/>
and here "ed" is nothing but the bean reference for a.b.c.MyCustomDataExtractor.
<bean id="ed" class="a.b.c.MyCustomDataExtractor"/>

Spring Webflow Flow Registry Configuration

Please bear with me as this is my first question. Let me know what I can do to improve future questions.
I am trying to learn Spring Webflow, and am slowly wrapping my head around it. I am finding that there are a lot of conventions that the programmer is expected to "just know", and the examples online don't seem to work.
I have cobbled together one example that works as expected, but now I am trying to extend my understanding to the next level in another small project, with my long term goal being a much more complex application. The goal of this exercise is to build a login system that supports different types of client (phone, desktop, etc) with different webflows.
As near as I can tell, I am having trouble configuring the flow registry, probably because I am misunderstanding the convention.
The textbook example I am emulating is this:
<!-- The registry of executable flow definitions -->
<webflow:flow-registry flow-builder-services="flowBuilderServices"
id="flowRegistry" base-path="/WEB-INF/flows/">
<webflow:flow-location path="/welcome/welcome.xml" />
</webflow:flow-registry>
My configuration is this:
<!-- The registry of executable flow definitions -->
<webflow:flow-registry id="flowRegistry"
flow-builder-services="flowBuilderServices"
base-path="/WEB-INF/pages/">
<webflow:flow-location path="d/login.xml" />
<webflow:flow-location path="d/signup.xml" />
</webflow:flow-registry>
The log states:
DEBUG o.s.w.d.r.FlowDefinitionRegistryImpl - Registering flow definition 'ServletContext resource [/WEB-INF/pages/d/login.xml]' under id 'd'
DEBUG o.s.w.d.r.FlowDefinitionRegistryImpl - Registering flow definition 'ServletContext resource [/WEB-INF/pages/d/signup.xml]' under id 'd'
Since, under the covers, the flow registry is a simple HashMap, only one of the flow files is being registered, and not as what I would expect.
What am I missing?
Change configuration as mentioned below, this might help you:
<webflow:flow-registry id="flowRegistry"
flow-builder-services="flowBuilderServices"
base-path="/WEB-INF/pages">
<webflow:flow-location path="/d/login.xml" />
<webflow:flow-location path="/d/signup.xml" />
</webflow:flow-registry>
also see Spring Webflow - How to Get List of FLOW IDs

Bean Autowiring problem

I am starter in mutithreading. I am trying to index my data into solr.For that I was writing the following code
I am getting null pointer exception in the line highlighted
You need to add the following:
<context:annotation-config/>
You need to set the path for autowiring package scan and in your case it will be:
<context:component-scan base-package="a.b.c" />
After it you need to mark the class as candidate for autowiring:
#Component("indexTask")
#Scope("prototype")
IndexTask implements Callable<IndexObject>
{
//ommited
}
Next you can remove indexTask bean configuration from xml file. your package will be created automatically.
Hope it helps.
Autowiring doesn't happen automatically, you need to configure it. See the Spring docs for detail, but essentially you need to add
<context:annotation-config/>

Resources