how to write class to do Database operation - spring integeration - spring-integration

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.

Related

Oracle ADF Unexpected Null Pointer Exception When accessing view objects in a seperate thread

I have a webservice in adf that treats requests, I use methods from a jar that run through view object iterators and so on.
In treating a request I call a method from the said jar that initializes a separate thread that manipulates and compares rows from view objects in that separate thread,
I am getting random exceptions like the following:
## Detail 0 ##
java.lang.NullPointerException
at oracle.jbo.server.ViewRowSetIteratorImpl.initViewRowSetIteratorImpl(ViewRowSetIteratorImpl.java:227)
at oracle.jbo.server.ViewRowSetIteratorImpl.(ViewRowSetIteratorImpl.java:176)
at oracle.jbo.server.ViewRowSetImpl.createNewRowSetIterator(ViewRowSetImpl.java:1434)
at oracle.jbo.server.ViewRowSetImpl.createViewRowSetIterator(ViewRowSetImpl.java:1485)
at oracle.jbo.server.ViewRowSetImpl.getDefaultRowSetIterator(ViewRowSetImpl.java:1704)
at oracle.jbo.server.ViewRowSetImpl.setRangeSize(ViewRowSetImpl.java:2936)
at oracle.jbo.server.ViewObjectImpl.doCreateViewLinkAccessorRS(ViewObjectImpl.java:16080)
at oracle.jbo.server.ViewObjectImpl.createViewLinkAccessorRS(ViewObjectImpl.java:16171)
at oracle.jbo.server.AssociationDefImpl.get(AssociationDefImpl.java:472)
at oracle.jbo.server.ViewAttributeDefImpl.get(ViewAttributeDefImpl.java:949)
at oracle.jbo.server.ViewRowStorage.getViewLinkAccessorResult(ViewRowStorage.java:1528)
at oracle.jbo.server.ViewRowStorage.getAttributeInternal(ViewRowStorage.java:1827)
at oracle.jbo.server.ViewRowImpl.getAttributeValue(ViewRowImpl.java:1923)
at oracle.jbo.server.ViewRowImpl.getAttributeInternal(ViewRowImpl.java:866)
and
## Detail 0 ##
java.lang.NullPointerException
at oracle.jbo.server.ViewRowImpl.getUseViewLogicGroupDef(ViewRowImpl.java:6078)
at oracle.jbo.server.ViewRowStorage.getViewAttributeDef(ViewRowStorage.java:1432)
at oracle.jbo.server.ViewRowStorage.getAttributeInternal(ViewRowStorage.java:1778)
at oracle.jbo.server.ViewRowImpl.getAttributeValue(ViewRowImpl.java:1923)
at oracle.jbo.server.ViewRowImpl.getAttributeInternal(ViewRowImpl.java:866)
and
Caused by: java.lang.NullPointerException
at oracle.jbo.server.ViewRowSetIteratorImpl.initViewRowSetIteratorImpl(ViewRowSetIteratorImpl.java:227)
at oracle.jbo.server.ViewRowSetIteratorImpl.(ViewRowSetIteratorImpl.java:176)
at oracle.jbo.server.ViewRowSetImpl.createNewRowSetIterator(ViewRowSetImpl.java:1434)
at oracle.jbo.server.ViewRowSetImpl.createViewRowSetIterator(ViewRowSetImpl.java:1485)
at oracle.jbo.server.ViewRowSetImpl.getDefaultRowSetIterator(ViewRowSetImpl.java:1704)
at oracle.jbo.server.ViewRowSetImpl.setRangeSize(ViewRowSetImpl.java:2936)
at oracle.jbo.server.ViewObjectImpl.doCreateViewLinkAccessorRS(ViewObjectImpl.java:16080)
at oracle.jbo.server.ViewObjectImpl.createViewLinkAccessorRS(ViewObjectImpl.java:16171)
at oracle.jbo.server.AssociationDefImpl.get(AssociationDefImpl.java:472)
at oracle.jbo.server.ViewAttributeDefImpl.get(ViewAttributeDefImpl.java:949)
at oracle.jbo.server.ViewRowStorage.getViewLinkAccessorResult(ViewRowStorage.java:1528)
at oracle.jbo.server.ViewRowStorage.getAttributeInternal(ViewRowStorage.java:1827)
at oracle.jbo.server.ViewRowImpl.getAttributeValue(ViewRowImpl.java:1923)
at oracle.jbo.server.ViewRowImpl.getAttributeInternal(ViewRowImpl.java:866)
The same method when it runs without the jar ( same code like in the jar but as a part of the same project ), it executes perfectly fine.
Could you please tell me why a NullPointerException is raised?
Thanks
You can not use the Business Components(ViewObject,Entities... etc) inside a thread.
There is no context (FacesContext cannot be initialized ).So you have to pass the ApplicationModule as a paramter to your method. But it will take a lot of time for processing
So the best way to access your data is to use CallableStatments PreparedStatments with Java Data Source connection.

How to get query string in case CQLStatement,QueryState and QueryOptions is given

Cassandra has org.apache.cassandra.cql3.QueryHandler interface which provide apis to handle external queries from client.
Below api which handles prepared statment:
public ResultMessage processPrepared(CQLStatement statement, QueryState state, QueryOptions options) throws RequestExecutionException, RequestValidationException;
I want to log queryString and value passed to it, in case CQLStatement,QueryState and QueryOptions is given . How can i get it?
I Believe a person who has worked on cassandra code can help me out in this.
This would be very difficult in 2.1. With newer versions where for logging they needed this they just recreate it as well as possible. You can see how in the ReadCommand implementations, theres a name() or toCQLString() used in things like slow query logging. You could backport this and the 2 implementations of appendCQLWhereClause for ability to do similar and then build one for modification statement.
in getPrepared() you can get the rawCQLStatement from the ParsedStatement.Prepared and stash it in the thread local.
You may want to alternatively consider using a custom implementation of tracing (example) or using triggers and building a mutation logger.
Do the following:
create a class that would implement the QueryHandler interface and make Cassandra aware of it
in that class you can maintain a list of the queries (add to this list when prepare method is being called) and the current query that you will get from the list when getPrepared it's called; you can get it from the list using the MD5Digest id
when processPrepared is called you can replace the ? in the query string with the values in the QueryOptions options.getValues().
HTH

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 cache does work w/ nested method

I has one method to call another #Cacheable method like this:
public ItemDO findMethod2(long itemId) {
this.findMethod1(itemId);
...
}
#Cacheable(value = "Item", key="#itemId", unless="#result == null")
public ItemDO findMethod1(long itemId) {
...
}
The cache works well if I call the findMethod1() directly. However, when I call findMethod2() the the cache on findMethod1() is totally ignored.
Could it be the trick made by JVM which inline the findMethod1() into findMethod2()?
Does anyone come across similar issue?
Thanks!
It's no JVM trick, i.e. findMethod1() is not being inlined inside findMethod2() or anything of that nature.
The problem is your code is bypassing the "Proxy" that Spring is creating around your application class (containing findMethod1()) for the #Cacheable annotation.
Like Spring's Transactional annotations and underlying infrastructure, given an interface, by default Spring will create a JDK Dynamic Proxy (AOP style) to "intercept" the method call and apply the "advice" (as determined by the type of annotation, in this case, caching). However, once the target object is invoked from the interceptor (Proxy) acting on behalf of the target object to apply the advice, the Thread is now executing in the context of the target object so any subsequent method invocations from within the target object are occurring directly on the target object itself.
It looks a little something like this...
caller -> Proxy -> findMethod2() -> findMethod1()
Ideally what you want is this...
caller -> Proxy -> findMethod2() -> Proxy -> findMethod1()
However, the Thread is already executing in the context of the "target" object once inside findMethod2(), so you end up with the first call stack.
The Spring doc explains it better here.
The document goes on to point out solutions to this problem, the most favorable is refactoring your code to ensure the caller is going through the Proxy interceptor for the 2nd method invocation (i.e. findMethod1()).
I also gather another solution to this problem would be to use full-blown AspectJ, using a compiler and byte-code weaver during your application build process to modify the actual target object so that subsequent invocations from within the target object intercept and apply the advice accordingly.
See the Spring docs on the trade-offs between Spring AOP and full AspectJ, as well as how to use full AspectJ in your Spring applications.
Hope this helps.
Cheers!
Other solution I find handy is using #Resource and then invoking the target (method1 in your case) using that resource reference with https://stackoverflow.com/a/48867068/2488286

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

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>

Resources