Expression in service activator doesn't execute (Spring Integration) - spring

I debug my app and the expression doesn't execute.
<bean id="remover" class="org.example.Remover"/>
<bean id="key" class="java.lang.String">
<constructor-arg value="KEY"/>
</bean>
<integration:service-activator input-channel="middleChannel"
expression="#remover.remove(key)"/>
No Exception. method doesn't call.

That’s not true: there must be an exception. You don’t show the whole flow to determine the part who swallows your exception on the matter.
Your expression is like:
#remover.remove(key)
You correctly call remover bean, but there is no such a property like key in the Message object - just only headers and payload. That’s why I’m making a conclusion that you have problems.
You can turn on debug logs for the Spring Integration category and follow you the trace of the call.

Related

Please configure a TransactionTemplate on the transacted policy

I implement a Spring Boot (1.5.x) application with Apache Camel (2.19)
For integration purposes I need to use three data sources (see for more about multi-data-sources here: https://github.com/spring-projects/spring-data-examples/tree/master/jpa/multiple-datasources).
One of the routes I have marked with .transacted():
from(Consts.DIRECT_ROUTE + routeId)
.routeId(routeId)
.startupOrder(loadRouteParameters.getStartupOrderTransformAndLoad())
.autoStartup(true)
.transacted()
however, when I start the app I get:
Caused by: java.lang.IllegalArgumentException: Found 3 PlatformTransactionManager in registry. Cannot determine which one to use. Please configure a TransactionTemplate on the transacted policy.
How to handle it? How to fulfill "Please configure a TransactionTemplate". I was not able to find any example for this special case.
Sounds like you have multiple TransactionManager beans in your Spring context. Camel does not know which one to take. You have to help your Camel a bit.
Define a SpringTransactionPolicy and reference the TransactionManager to be used in the Camel route.
<bean id="txPolicyName" class="org.apache.camel.spring.spi.SpringTransactionPolicy">
<property name="transactionManager" ref="[yourTxManagerBeanId]" />
</bean>
Then you can set the policy as argument to your transacted() in the Camel route:
.transacted("txPolicyName") // txPolicyBeanId as String

Scoped proxy tag not taking effect - configuration error?

I've inherited a bit of a monster system. It is a Spring framework server meant to run on Weblogic.
The code as it stands seems to work perfectly for another developer. I can clean, compile and package the project without error. However, when I try to deploy the generate .war file to my Weblogic server, I get the following error:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'scopedTarget.com.example.portal.uil.delegate.ExceptionLogDelegate': Scope 'session' is not active for the current thread; consider defining a scoped proxy for this bean if you intend to refer to it from a singleton; nested exception is java.lang.IllegalStateException: No thread-bound request found: Are you referring to request attributes outside of an actual web request, or processing a request outside of the originally receiving thread? If you are actually operating within a web request and still receive this message, your code is probably running outside of DispatcherServlet/DispatcherPortlet: In this case, use RequestContextListener or RequestContextFilter to expose the current request.
This error points me to the following bean, which is in an external library:
<bean id="com.externalLibrary.ExceptionLogDelegate" class="com.externalLibrary.ExceptionLogDelegate" scope="session">
<aop:scoped-proxy />
<property name="errorLogBuffer" ref="com.externalLibrary.ErrorLogDao" />
</bean>
After searching around for that error for a while, it seems that it is most often experienced when the aop:scope-proxy tag is omitted. This bean is being loaded as such:
<bean id="exceptionResolver" class="foo.mypackage.SoapFaultDetailExceptionResolver">
<property name="marshaller" ref="marshaller"/>
<property name="exceptionLogDelegate" ref="foo.mypackage.ExceptionLogDelegate"/>
</bean>
The strange thing is that with no files changed, this exact code works fine on my colleague's machine, so I assume I'm missing some magic configuration step.
Could anyone perhaps point me at thing to look for?
Kind Regards

Programatically set v$session program property

I found some answers on the problem but none that i could make work in my case. My problem is that I load a datasource from my JBoss configuration with spring:
<xa-datasource jndi-name="java:jboss/jdbc/oracleDatasource" pool-name="jdbc/oracleDatasource" enabled="true">
<xa-datasource-property name="URL">
jdbc:oracle:thin:#URL:1522:SID
</xa-datasource-property>
<xa-datasource-property name="connectionProperties">
v$session.program=MyAPP
</xa-datasource-property>
<driver>oracle-jdbc</driver>
The spring loading is made as follows:
<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="java:jboss/jdbc/oracleDatasource"/>
</bean>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<constructor-arg ref="dataSource"/>
</bean>
As you can see, I have set the v$session.program property in JBoss, it works well.
The problem is that i have several applications (war) that can be deployed on the same JBoss server, using this configuration. What I want to do in this case is to have each of my application to have its own name written in the v$session.program property.
So basically, i would like to be able to load the same datasource on each app but to have each of them using its own name to log the program property in oracle DB. Is it possible or do I have to have one datasource for each application hosted?
The only thing you need it to intercept each call of getConnection from connection pool.
You must obtain a real Oracle connection - not a proxy - and call the setClientInfo on 12c or setEndToEndMetrics in older versions to set the action / client / module identification.
An example see here.
Also note that the use of dbms_application_info for this same purpose works as well, but this produces a one server roundtrip too much. The setClientInfo doesn't produce server call, but stores this information for the next statement execution (which is the preformance saving approach).
Also note that to use this feature, your driver must match perfectly with your database - the strange exeptions you can see while setting teh client info are in most cases caused by the incompatibility of teh JDBC driver and the RDBMS.
If putting this information into v$session.module or v$session.client_info is an option, you can do using Java code.
All you need to do is call dbms_application_info.set_module() or dbms_application_info.set_client_info() after your Java code obtained the connection from the datasource.
Something like this:
Connection conn = ... // get connection from the DataSource
CallableStatement cstmt = conn.prepareCall("{call dbms_application_info.set_client_info(?)}");
cstmt.setString(1, "Some interesting information");
cstmt.execute();

BeanCreationException during acceptance tests

I use Spring Security to authentication.
I modified my annotation #Page which define which type of user is able to access page.
After that in my acceptance tests i started to get errors in:
public void login(#Named("email") String email, #Named("password") String password) {
fillUpLoginForm(email, password);
waitForElement(MosquitoElements.MainNavigationBar.LOGOUT);
securityService.login(email, password); // authenticates user in test environment too
}
i found that there's something wrong here:
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(email, password);
getSecurityContext().setAuthentication(authenticationManager.authenticate(token));
What can cause problem?
Error:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'scopedTarget.securityContext': Scope 'session' is not active for the current thread; consider defining a scoped proxy for this bean if you intend to refer to it from a singleton; nested exception is java.lang.IllegalStateException: No thread-bound request found: Are you referring to request attributes outside of an actual web request, or processing a request outside of the originally receiving thread? If you are actually operating within a web request and still receive this message, your code is probably running outside of DispatcherServlet/DispatcherPortlet: In this case, use RequestContextListener or RequestContextFilter to expose the current request.
Change in annotation:
before
boolean requiresAdminPrivileges() default false;
after
Authorities[] requiredAuthorities();
In appliaction everything works fine, only tests have probles.
Try to emulate sesseion scope in your test's application context:
<bean class="org.springframework.beans.factory.config.CustomScopeConfigurer">
<property name="scopes">
<map>
<entry key="session">
<bean class="org.springframework.context.support.SimpleThreadScope"/>
</entry>
</map>
</property>
</bean>

Spring SimpleMappingExceptionResolver not going to default view

I am playing with the SimpleMappingExceptionResolver to see how it works and to see if it will be of use to us for a client but I am having problems understanding it.
What I have tried is visiting a particular page in my application and having it throw an exception in the handleRequestInternal method.
When I throw a RecoverableDataAccessException (subclass of DataAccessException) then the correct error page is displayed as expected.
When I throw a freemarker.core.InvalidReferenceException or java.lang.NumberFormatException then the exception bubbles through to the page and the default 500 error page (ie, no styling) is shown.
Below is the mapping I am using.
<bean id="exceptionResolver" class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<property name="exceptionMappings">
<props>
<prop key="org.springframework.dao.DataAccessException">/general/error/500</prop>
<prop key="freemarker.core.InvalidReferenceException">/general/error/500</prop>
<prop key="NumberFormatException">/general/error/500</prop>
</props>
</property>
<property name="defaultErrorView" value="/general/error/500" />
</bean>
I at least expected the default error view to get hold of the exception and display my specific error page but that is not happening.
Am I using the SimpleMappingExceptionHandler correctly here?
[edit] I am using jetty.
[edit] I've realised that the SMER doesn't handle errors thrown during render which explains why it can't catch the ones I've specifically having trouble with. Can the SMER be made to cope with 500 style errors?
As you've discovered, SimpleMappingExceptionResolver will not work for exceptions thrown in the view layer. It implements the interface HandlerExceptionResolver which, as the name implies, only handles exceptions thrown by the handler (i.e. the controller).
If you need to handle exceptions thrown by the view, you can either write a HandlerInterceptor, overriding the afterCompletion() method, or write a non-Spring servlet Filter. In both cases, you won't get the benefit of Spring's view resolver, you'll have to handle rendering yourself.
One word of warning, though - when you get exceptions in the view layer, it's not always possible to handle them gracefully, since the server may have begun to flush the view output to the client when the exception is thrown, in which case the server cannot then render a separate error page. This is why it's good practice to do as much logic as you can in the controller layer, so that exceptions are caught as early as possible.

Resources