No adapter for handler in Spring MVC - scala

I have problem with simple spring mvc controller written in scala:
#Controller
class HelloWorldController {
implicit def sessionFactory2Session(sf: SessionFactory) = sf.getCurrentSes
#Autowired
var sessionFactory: SessionFactory = null
#Transactional
#RequestMapping(value=Array("/hello.html"),method = Array(RequestMethod.GET,RequestMethod.POST))
def showHello = {
val document = new CustomDocument("name","custom")
sessionFactory.save(document)
sessionFactory.flush
"helloPage"
}
}
When I tried to access /hello.html I received exception:
javax.servlet.ServletException: No adapter for handler: Does your handler implement a supported interface like Controller?
at org.springframework.web.servlet.DispatcherServlet.getHandlerAdapter(DispatcherServlet.java:951)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:758)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:717)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:644)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:549)
But when I removed #Transactional annotation - everything works!!. Spring can't find request mapping with two annotations? My applicationContext.xml fragment:
<bean id="openSessionInViewInterceptor"
class="org.springframework.orm.hibernate3.support.OpenSessionInViewInterceptor">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
<property name="interceptors">
<list><ref bean="openSessionInViewInterceptor"/></list>
</property>
<property name="alwaysUseFullPath" value="true" />
</bean>
<context:component-scan base-package="scala.hibernate"/>
<bean id="viewResolver" class="org.springframework.web.servlet.view.UrlBasedViewResolver">
<property name="viewClass"
value="org.springframework.web.servlet.view.JstlView"/>
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>
<!-- for transaction -->
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManaager">
<property name="sessionFactory" ref="sessionFactory"/>
<property name="dataSource" ref="dataSource"/>
</bean>
<tx:annotation-driven/>
EDIT
Transactional aspect is applied using dynamic proxy, and it prevents Spring MVC from accessing the #RequestMapping annotations on the target class
Solution:
<tx:annotation-driven proxy-target-class="true"/>

Try adding <context:annotation-config /> to your applicationContext.xml and see if that fixes the problem.

declare following bean . this should solve the problem
<bean id="simpleHandler" class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/>
will update you once find out the root cause..

Related

groovy + spring integration jpa: linkage error

Using Spring integration JPA + Groovy
I got the following error:
Could not instantiate bean class [org.springframework.integration.jpa.core.JpaExecutor]: Constructor threw exception; nested exception is java.lang.LinkageError: loader constraint violation: loader (instance of groovy/lang/GroovyClassLoader) previously initiated loading for a different type with name "javax/persistence/LockModeType"
Here are my dependencies :
dependencies {
compile 'org.springframework.integration:spring-integration-jpa:3.0.4.RELEASE'
compile 'org.apache.openjpa:openjpa:2.3.0'
compile group: 'hsqldb', name: 'hsqldb', version: '1.8.0.10'
compile 'org.codehaus.groovy:groovy-all:2.3.6'
}
Here is my spring context :
<int-jpa:inbound-channel-adapter
channel="jpaInboundChannel"
entity-manager="entityManagerFactory"
jpa-query="select p from Person p"
auto-startup="true" >
<int:poller fixed-rate="2000">
</int:poller>
</int-jpa:inbound-channel-adapter>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<constructor-arg ref="entityManagerFactory" />
</bean>
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="jpaVendorAdapter" ref="vendorAdaptor" />
<property name="packagesToScan" value="com.univ"/>
</bean>
<jdbc:embedded-database id="dataSource" type="HSQL" />
<bean id="vendorAdaptor" class="org.springframework.orm.jpa.vendor.OpenJpaVendorAdapter"
parent="abstractVendorAdaptor">
</bean>
<bean id="abstractVendorAdaptor" abstract="true">
<property name="generateDdl" value="true" />
<property name="database" value="HSQL" />
<property name="showSql" value="false"/>
</bean>
<int:service-activator input-channel="jpaInboundChannel" ref="service" method="method"></int:service-activator>
<bean id="service" class="com.univ.Service" />
The Groovy main programs contains :
ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath:META-INF/applicationContext.xml")
What can I do ? Thank you.

Spring Batch Database Dependency pass parameters to SQL statement

I want separate the sql from the batch.xml file, so I defined the sql statement into a properties file. Inside the batch.xml I bind the property-placeholder bean then point to the properties file.
For simple select statement should not be a problem. But if I want to pass the parameter as where clause condition is it possible to do that?
<context:property-placeholder
location="classpath:batch-sql.properties/>
<bean id="secondReader"
class="org.springframework.batch.item.database.JdbcCursorItemReader"
scope="step">
<property name="dataSource" ref="dataSource" />
<property name="sql" value="${sql1}" />
<property name="rowMapper">
<bean class="com.test.batchjob.process.TestPersonMapper" />
</property>
</bean>
This is my sql statment in properties file:
SELECT * FROM Person WHERE id = ?
Can the id pass from jobparameter?
To set the parameters of the query in a JdbcPagingItemReader, you have to use the property parametersValue. This property takes a Map<String,Object> where the key is either the named parameter or the index of the parameter (if you use ?).
<bean id="secondReader"
class="org.springframework.batch.item.database.JdbcPagingItemReader"
scope="step">
<property name="queryProvider">
<bean class="org.springframework.batch.item.database.support.SqlPagingQueryProviderFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="selectClause" value="select *" />
<property name="fromClause" value="from persons" />
<property name="whereClause" value="where id = ?" />
</bean>
</property>
<property name="parametersValue">
<map>
<entry key="1" value="#{jobParameters['id']}" />
</map>
</property>
<property name="rowMapper">
<bean class="com.test.batchjob.process.TestPersonMapper" />
</property>
</bean>
See documentation : JdbcPagingItemReader
UPDATE
You have to use a QueryProvider instead of sql and datasource properties.
You can replace the text of the query by values of the properties file.
To set the parameters of the query in a JdbcCursorItemReader, you have to use the property preparedStatementSetter. This property takes a PreparedStatementSetter which you have to implement yourself to set either named or index-based parameters.
<bean id="secondReader"
class="org.springframework.batch.item.database.JdbcCursorItemReader"
scope="step">
<property name="sql" value="${sql1}" />
<property name="itemPreparedStatementSetter">
<bean class="xx.xx.xx.YourPreparedStatementSetter">
<property name="id" value="#{jobParameters['id']}" />
</bean>
</property>
<property name="rowMapper">
<bean class="com.test.batchjob.process.TestPersonMapper" />
</property>
An example implementation of a PreparedStatementSetter :
public class YourPreparedStatementSetter implements PreparedStatementSetter {
private String id;
#Override
public void setValues(PreparedStatement ps) throws SQLException {
ps.setString(1, this.id);
}
public setId(String id) {
this.id = id;
}
}
For JdbcCursorItemReader, you can take a look at answer here : Using Spring Batch JdbcCursorItemReader with NamedParameters

How to invoke sftp:outbound-gateway from spring batch?

I would like to invoke sftp:outbound-gateway from batch tasklet in order to download a file from sftp server.
I've seen other posts related to this subject but I'm not sure what am I doing wrong. Could anybody give me a hint based on my configuration? My batch works so the problem is just to ivoke the sftp component in batch step. I've marked the Spring Integration section with comment so it is easier to read just a relevant configuration.
I can see in my logs: DEBUG [o.s.i.e.SourcePollingChannelAdapter] Received no Message during the poll, returning 'false'. So I am not receiving a file but why?
Thanks in advance for your time spend on analysis!
<bean id="ftsSftpClientFactory" class="org.springframework.integration.sftp.session.DefaultSftpSessionFactory">
<property name="host" value="${my.import.sftp.localhost}"/>
<property name="user" value="${my.import.sftp.username}"/>
<property name="password" value="${my.import.sftp.passwort}"/>
</bean>
<!-- Start: Spring Integration -->
<int:channel id="replyChannel" >
<int:queue/>
</int:channel>
<int:channel id="requestChannel" />
<int-sftp:outbound-gateway id="sftpGateway"
session-factory="ftsSftpClientFactory"
request-channel="requestChannel"
reply-channel="replyChannel"
auto-startup="true"
command="get"
command-options="-P"
expression="payload"
remote-directory="."
local-directory="${my.import.sftp.copy.file.destinationpath}">
</int-sftp:outbound-gateway>
<bean name="copyFileTasklet" class="com.mydomain.CopyFileTasklet">
<property name="channel" ref="replyChannel" />
<property name="pollableChannel" ref="requestChannel" />
</bean>
<!-- Start: Spring Batch -->
<bean name="myImportTask" class="com.mydomain.MyImportTask">
<property name="job" ref="unternehmungImportJob"/>
<property name="jobLauncher" ref="jobLauncher"/>
</bean>
<bean id="jobDetail"
class="com.mydomain.MyImportJob">
<property name="myImportTask" ref="myImportTask" />
</bean>
<!--suppress SpringBatchModel -->
<batch:job id="myImportJob">
<batch:step id="copy-file-step" next="my-import-step">
<batch:tasklet ref="copyFileTasklet"/>
</batch:step>
<batch:step id="my-import-step">
<batch:tasklet>
<batch:chunk reader="myItemReader"
writer="myItemWriter"
commit-interval="10000">
<!--
skip-limit="10000"
<batch:skippable-exception-classes>
<batch:include class="java.lang.Exception"/>
<batch:exclude class="java.io.FileNotFoundException"/>
</batch:skippable-exception-classes> -->
</batch:chunk>
<batch:transaction-attributes isolation="DEFAULT" propagation="REQUIRED"/>
</batch:tasklet>
</batch:step>
</batch:job>
<bean id="myItemReader" scope="step" class="org.springframework.batch.item.file.FlatFileItemReader">
<property name="linesToSkip" value="1"/>
<property name="encoding" value="${my.import.batch.encoding}" />
<property name="resource" value="${my.import.batch.input.resource}"/>
<property name="lineMapper">
<bean class="org.springframework.batch.item.file.mapping.DefaultLineMapper">
<property name="lineTokenizer" ref="lineTokenizer"/>
<property name="fieldSetMapper">
<bean class="com.mydomain.MyImportMapper"/>
</property>
</bean>
</property>
</bean>
<bean id="myItemWriter" class="com.mydomain.MyItemWriter">
<property name="myApplicationService" ref="defaultmyApplicationService" />
</bean>
<bean id="lineTokenizer" class="com.mydomain.DelimitedLineTokenizerWithEOF">
<property name="delimiter" value="${my.import.batch.delimiter}" />
<property name="eofMarker" value="${my.import.batch.eof.marker}" />
</bean>
public class CopyFileTasklet implements Tasklet {
private MessageChannel requestChannel;
private PollableChannel replyChannel;
public void setRequestChannel(MessageChannel requestChannel) {
this.requestChannel = requestChannel;
}
public void setReplyChannel(PollableChannel replyChannel) {
this.replyChannel = replyChannel;
}
#Override
public RepeatStatus execute(StepContribution stepContribution, ChunkContext chunkContext) throws Exception {
Message<?> result = replyChannel.receive(10000);
Object file = result.getPayload();
return RepeatStatus.FINISHED;
}
}
Your issue that you don't inititate Integration Flow from your custom Tasklet. Of course you can't receive anything from the replyChannel, if you haven't sent request before.
If you just need to process Integration Flow and get result from it, it would be better to use POJI <gateway> from that Tasklet:
public interface SftpGateway {
File download(String fileName);
}
<gateway id="sftpGateway" service-interface="com.my.proj.SftpGateway"
default-request-channel="requestChannel"/>
<bean name="copyFileTasklet" class="com.mydomain.CopyFileTasklet">
<property name="sftpGateway" ref="sftpGateway" />
</bean>
Something like that.

How to use httpClient to 4.3 in Spring WS 2.14?

With Httpclient 3 my Spring bean definition was
<bean id="messageSender"
class="org.springframework.ws.transport.http.CommonsHttpMessageSender">
<constructor-arg>
<bean class="org.apache.commons.httpclient.HttpClient">
<constructor-arg>
<bean
class="org.apache.commons.httpclient.MultiThreadedHttpConnectionManager">
<property name="params">
<bean
class="org.apache.commons.httpclient.params.HttpConnectionManagerParams">
<property name="defaultMaxConnectionsPerHost" value="XX" />
<property name="maxTotalConnections" value="XX" />
<property name="staleCheckingEnabled" value="false" />
<property name="tcpNoDelay" value="false" />
<property name="soTimeout" value="XXXXX" />
<property name="connectionTimeout"
value="XXXX" />
</bean>
</property>
</bean>
</constructor-arg>
</bean>
</constructor-arg>
I want a similar bean configuration with the httpclient 4.3 classes.
I needed NTLMv2 authentication on my connection and I was able to succesfully use 4.x by configuring spring with the classes attached to this issue: https://jira.spring.io/browse/SWS-563
Here's a piece of my #Configuration:
#Bean public WebServiceTemplate webserviceTemplate() {
WebServiceTemplate webserviceTemplate = new WebServiceTemplate();
webserviceTemplate.setMessageSender(messageSender());
return webserviceTemplate;
}
#Bean public WebServiceMessageSender messageSender() {
HttpClientMessageSender messageSender = new HttpClientMessageSender();
// do 4.x specific configuration
return messageSender;
}

Spring Data JPA with a custom RepositoryFactory and Multiple EntityManagers

I'm currently trying to get Spring Data JPA to work with two DataSources and thus two EntityManagers. My Repositories all inherit from a custom base class "BaseRepositoryImpl".
Problem:
I always get the following exception:
org.springframework.beans.factory.NoSuchBeanDefinitionException:
No unique bean of type [javax.persistence.EntityManagerFactory] is defined:
expected single bean but found 2: entityManagerFactory1,entityManagerFactory2
Question:
How can I tell my custom RepositoryFactory which EntityManagerFactory to use?
Here's my Spring configuration:
<jpa:repositories base-package="package1" transaction-manager-ref="..."
factory-class="MyFactoryBean"
entity-manager-factory-ref="entityManagerFactory1"/>
<bean id="dataSource1" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="..." />
</bean>
<bean id="entityManagerFactory1" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource1" />
<property name="persistenceUnitName" value="unit1" />
...
</bean>
<jpa:repositories base-package="package2" transaction-manager-ref="..."
factory-class="MyFactoryBean"
entity-manager-factory-ref="entityManagerFactory2"/>
<bean id="dataSource2" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="..." />
</bean>
<bean id="entityManagerFactory2" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource2" />
<property name="persistenceUnitName" value="unit2" />
...
</bean>
The class "MyFactoryBean" is implemented exactly as described at http://docs.spring.io/spring-data/jpa/docs/1.4.x/reference/htmlsingle/#repositories.custom-behaviour-for-all-repositories.
The configuration "entity-manager-factory-ref" seems to be ignored by Spring, at least when using a custom RepositoryFactory.
Any hints?
Entity manager factory is used to create entity managers for different persistence units. You declare your entity manager bean and then give entity manager factory bean as it's class.
This is what worked for me:
<tx:annotation-driven transaction-manager="transactionManager" />
<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor"/>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="defaultEntityManager"/>
</bean>
<bean id="defaultDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="${hibernate.connection.driver_class}"/>
<property name="url" value="${db.default.url}"/>
<property name="username" value="${db.default.username}"/>
<property name="password" value="${db.default.password}"/>
</bean>
<bean id="defaultEntityManager" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="defaultDataSource"/>
<property name="persistenceUnitName" value="defaultPersistenceUnit"/>
</bean>
<bean id="otherDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="${hibernate.connection.driver_class}"/>
<property name="url" value="${db.other.url}"/>
<property name="username" value="${db.other.username}"/>
<property name="password" value="${db.other.password}"/>
</bean>
<bean id="otherEntityManager" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="otherDataSource"/>
<property name="persistenceUnitName" value="otherPersistenceUnit"></property>
</bean>
Then when you are implementing your data access classes just declare:
#Repository
#Transactional
public class MyDAOImpl implements MyDAO
{
#PersistenceContext(unitName = "defaultPersistenceUnit")
private EntityManager entityManager;
}
and for DAO that uses other persistence unit:
#Repository
#Transactional
public class MyOtherDAOImpl implements MyOtherDAO
{
#PersistenceContext(unitName = "otherPersistenceUnit")
private EntityManager entityManager;
}