Spring Data-Rest + Spring MVC - spring

I am mixing Spring MVC with Spring Data-Rest and my User repository is of this form:
#RepositoryRestResource(collectionResourceRel = "users", path = "users")
public interface UserRepository extends PagingAndSortingRepository<User, Integer> {
}
My servletContext.xml has the following properties:
<mvc:annotation-driven/>
<bean class="org.springframework.data.rest.webmvc.config.RepositoryRestMvcConfiguration"> </bean>
<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/views/"/>
<property name="suffix" value=".jsp"/>
</bean>
<mvc:default-servlet-handler/>
Right now my paths are of the form /myapp/users. How can I change it to be /myapp/rest/users?

Try adding configuration hook to your RepositoryRestMvcConfiguration bean:
#Configuration
#Import(RepositoryRestMvcConfiguration.class)
public class CustomConfigWithBasePath extends RepositoryRestMvcConfiguration
{
#Override
protected void configureRepositoryRestConfiguration(RepositoryRestConfiguration config)
{
super.configureRepositoryRestConfiguration(config);
try
{
config.setBaseUri(new URI("/rest"));
} catch (URISyntaxException e)
{
e.printStackTrace();
}
}
}
Otherwise, you can configure the BaseURI bean with a custom base uri as follows:
<bean id="baseUri" class="org.springframework.data.rest.webmvc.BaseUri">
<constructor-arg value="/rest"/>
</bean>
<bean class="org.springframework.data.rest.webmvc.config.RepositoryRestMvcConfiguration"
p:baseUri-ref="baseUri">
</bean>

Related

Tapestry-Spring Autowired dao is always null in service

We are working on a Tapestry5-Spring-Hibernate application.
We are using Tapestry 5.4.1, Spring 4.3.1.RELEASE and Hibernate 4.3.6.Final.
We are using and XML based application.
We are facing the problem that all daos #Autowired into spring services are always null. This will of course generate a NullpointerException everytime a dao is needed to perform an operation on the database.
We used generic service and dao interfaces
Here are the code samples:
Spring config file
<context:annotation-config />
<context:component-scan base-package="org.prism.forecast" />
<context:property-placeholder location="classpath:hibernate.properties" />
<!--Generic DAO -->
<bean id="appDao" primary="true" class="org.prism.forecast.dao.AppDaoImpl">
<property name="sessionFactory">
<ref bean="sessionFactory" />
</property>
</bean>
<!--Generic service-->
<bean id="appServiceImpl" class="org.prism.forecast.services.AppServiceImpl">
<property name="dao">
<ref bean="appDao" />
</property>
</bean>
<bean id="requestDao" class="org.prism.forecast.dao.RequestDaoImpl">
<property name="sessionFactory">
<ref bean="sessionFactory" />
</property>
</bean>
<bean id="requestServiceImpl" class="org.prism.forecast.services.RequestServiceImpl">
<property name="dao">
<ref bean="requestDao" />
</property>
</bean>
<bean id="SOPUploadDao" class="org.prism.forecast.dao.SOPUploadDaoImpl">
<property name="sessionFactory">
<ref bean="sessionFactory" />
</property>
</bean>
<bean id="SOPUploadServiceImpl" class="org.prism.forecast.services.SOPUploadServiceImpl">
<property name="dao">
<ref bean="SOPUploadDao" />
</property>
</bean>
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="packagesToScan" value="org.prism.forecast.entities" />
<property name="hibernateProperties">
<props>
<prop key="hibernate.hbm2ddl.auto">${hibernate.hbm2ddl.auto}</prop>
<prop key="hibernate.dialect">${hibernate.dialect}</prop>
</props>
</property>
</bean>
<bean id="dataSource" class="org.apache.tomcat.dbcp.dbcp.BasicDataSource">
<property name="driverClassName" value="${jdbc.driverClassName}" />
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
</bean>
<bean id="txManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate">
<property name="transactionManager" ref="txManager"/>
</bean>
<tx:annotation-driven transaction-manager="txManager" />
<bean id="persistenceExceptionTranslationPostProcessor"
class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"/>
Generic DAO Interface
public interface AppDao {
/**
* Finds an object by id
*
* #param <T>
* #param <PK>
* #param type
* #param id
* #return the object
*/
<T, PK extends Serializable> T find(Class<T> type, PK id);
//other methods
}
Generic DAO implementation
#Repository("appDao")
public class AppDaoImpl implements AppDao {
protected static final Logger logger = LoggerFactory.getLogger(RequestDaoImpl.class);
#Inject
protected Session session;
#Resource(name = "sessionFactory")
protected SessionFactory sessionFactory;
/**
* #param sessionFactory the sessionFactory to set
*/
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
#SuppressWarnings("unchecked")
public <T, PK extends Serializable> T find(Class<T> type, PK id) {
return (T) session.get(type, id);
}
//other methods
}
Request DAO
public interface RequestDao extends AppDao {
}
Request DAO Implementation
#Repository("requestDao")
public class RequestDaoImpl extends AppDaoImpl implements RequestDao {
}
Generic service
public interface AppService {
/**
* #param <T>
* #param <PK>
* #param type
* #param id
* #return the object
*/
<T, PK extends Serializable> T find(Class<T> type, PK id);
//Other methods
}
Generic service implementation
#Service("appService")
#Transactional(propagation = Propagation.REQUIRED, readOnly = true)
public class AppServiceImpl implements AppService {
#Autowired
private AppDao dao = null;
/**
* #return the dao
*/
public AppDao getDao() {
return dao;
}
/**
* #param dao
* the dao to set
*/
public void setDao(AppDao dao) {
this.dao = dao;
}
#Override
public <T, PK extends Serializable> T find(Class<T> type, PK id) {
return dao.find(type, id);//dao is null here
}
//other methods
}
Request Service
public interface RequestService extends AppService {
}
Request Service Implementation
#Service("requestService")
#Transactional(propagation = Propagation.REQUIRED, readOnly = true)
public class RequestServiceImpl extends AppServiceImpl implements RequestService {
#Autowired
private RequestDao dao;
#Override
public Request find(Request request) {
dao.find(request);
}
//other methods
}
Usage in Tapestry pages
public class ManageRequest{
//dao needed for persistence operations
#InjectService("requestService")
protected requestService service;
}
While debugging the application we figured out that the service has been properly injected into the page but the dao has not been injected into the service. Can anybody tell me what is going wrong here?
This looks like Spring configuration issue, could it be that you need to specify sub package of your DAO services explicitly in <context:component-scan ... />, i.e.:
<context:component-scan base-package="org.prism.forecast, org.prism.forecast.dao" />
Some hints: #Autowired service is null, and multiple packages in context:component-scan.

Spring Data lazyload does not LazyInitializationException

#Component
#Transactional
public class TestClass extends AbstractClass
{
#Autowire
ClassARepo classARepo;
#Override
public void test() {
ClassA classA = classARepo.findOne(1);
List<ClassB> list = classA.getClassBs();
list.size();
}
}
ClassB is mapped as onetomany and lazily loaded.
In the above code
classARepo.findOne(1);
Executes correctly. but
List<ClassB> list = classA.getClassBs();
list.size();
Fails with LazyInitializationException.
public interface ClassARepo extends CrudRepository<ClassA, Integer> {
}
Instance for TestA is created like the one below
#PersistJobDataAfterExecution
#DisallowConcurrentExecution
#Transactional
#Component
public class TestClassJOB extends AbstractJob
{
#Autowired
TestClass indexer;
}
Context:
<!-- JPA mapping configuration -->
<bean id="persistenceXmlLocation" class="java.lang.String">
<constructor-arg value="classpath:/persistence.xml"></constructor-arg>
</bean>
<!-- entity manager -->
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"
p:dataSource-ref="dataSource" p:persistenceUnitName="jpaData"
p:persistenceXmlLocation-ref="persistenceXmlLocation">
<property name="packagesToScan" value="com..persist.entity" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
</property>
</bean>
<!-- transaction manager -->
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"
p:entityManagerFactory-ref="entityManagerFactory" lazy-init="true" p:dataSource-ref="dataSource" />
<!-- JPA repositories -->
<jpa:repositories base-package="com..persist.repo"
entity-manager-factory-ref="entityManagerFactory" transaction-manager-ref="transactionManager" />
I tried many resources and could not solve the issue. The following error message is displayed "could not initialize proxy - no Session".
What could be the cause of the issue?
When the session is available while classARepo.findOne(1) is called, why is not available during lazy fetch(list.size())?
The issue was the instance for TestClassJOB was created by Quartz. So the transnational proxy was not applied to the class which was the reason for the issue.
I fixed the issue by declaring a transaction template
#Autowired
TransactionTemplate transactionTemplate;
and then wrapping the code within
transactionTemplate.execute(new TransactionCallbackWithoutResult()
{
#Override
protected void doInTransactionWithoutResult(TransactionStatus status)
{
<code here>
}
}

Bean creation exception in spring mobile

I am getting the following exception while using sample
nested exception is
org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [org.springframework.mobile.device.Device]: Specified class is an interface] with root cause
My controller is as follows:
package com.srccodes.spring.controller;
import java.util.logging.Logger;
import org.springframework.mobile.device.Device;
import org.springframework.mobile.device.site.SitePreference;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
/**
* #author Abhijit Ghosh
* #version 1.0
*/
#Controller
public class SpringMobileHelloController {
private static final Logger logger = Logger.getLogger(SpringMobileHelloController.class.getName());
#RequestMapping("/")
public String sayHello(SitePreference sitePreference, Device device, Model model) {
logger.info("SitePreference : " + sitePreference);
logger.info("Device : " + device);
model.addAttribute("message", "Hello World!");
return "helloWorld";
}
}
My dispatcher-servlet.xml is:
(some parts omitted)
<context:component-scan base-package="com.srccodes.spring.controller" />
<mvc:annotation-driven>
<mvc:argument-resolvers>
<bean class="org.springframework.mobile.device.site.SitePreferenceWebArgumentResolver" />
<bean class="org.springframework.mobile.device.DeviceWebArgumentResolver" />
</mvc:argument-resolvers>
</mvc:annotation-driven>
<mvc:interceptors>
<!-- Resolve the device which has generated the request -->
<bean class="org.springframework.mobile.device.DeviceResolverHandlerInterceptor" />
<!-- User's site preference -->
<bean class="org.springframework.mobile.device.site.SitePreferenceHandlerInterceptor" />
<!-- Redirects users to the device specific site -->
<bean class="org.springframework.mobile.device.switcher.SiteSwitcherHandlerInterceptor" factory-method="urlPath">
<constructor-arg value="/m" />
<constructor-arg value="/t" />
<constructor-arg value="/SpringMobileHelloWorld" />
</bean>
</mvc:interceptors>
<!-- Device aware view resolving -->
<bean id="liteDeviceDelegatingViewResolver" class="org.springframework.mobile.device.view.LiteDeviceDelegatingViewResolver">
<constructor-arg>
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/pages/" />
<property name="suffix" value=".jsp" />
</bean>
</constructor-arg>
<property name="mobilePrefix" value="m/" />
<property name="tabletPrefix" value="t/" />
<property name="enableFallback" value="true" />
</bean>
</beans>
Please help me out as I am a beginner in spring mobile.This example is available in spring source official website.It is saying that device is a interface but I have used its implementing classes only.Basically I think its an error in dispatcher servlet.xml
Try to use Device filter:
<filter>
<filter-name>deviceResolverRequestFilter</filter-name>
<filter-class>org.springframework.mobile.device.DeviceResolverRequestFilter</filter-class>
</filter>
Anyway, you can retrieve the device from DeviceUtils, using an HttpServletRequest, like this handler example..:
public boolean preHandle(HttpServletRequest request, HttpServletResponse arg1, Object arg2) throws Exception {
Device device = DeviceUtils.getCurrentDevice(request);
...
}
I have the same problem and solve it with the second approach.
Check if <mvc:annotation-driven/> is not defined anywhere else.
Simply add:
<mvc:annotation-driven>
<mvc:argument-resolvers>
<bean class="org.springframework.mobile.device.DeviceWebArgumentResolver" />
<bean class="org.springframework.mobile.device.site.SitePreferenceWebArgumentResolver" />
</mvc:argument-resolvers>
</mvc:annotation-driven>
In addition to leogps answer, following is the Java Config
#Bean
public DeviceHandlerMethodArgumentResolver deviceHandlerMethodArgumentResolver() {
return new DeviceHandlerMethodArgumentResolver();
}
#Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
argumentResolvers.add(deviceHandlerMethodArgumentResolver());
}
You have to add argument resolver for this.
Follow this
If you'd like to pass the current Device as an argument to one of your #Controller methods, configure a DeviceWebArgumentResolver:
<annotation-driven>
<argument-resolvers>
<bean class="org.springframework.mobile.device.DeviceWebArgumentResolver" />
</argument-resolvers>
</annotation-driven>
You can alternatively configure a DeviceHandlerMethodArgumentResolver using Java-based configuration:
#Bean
public DeviceHandlerMethodArgumentResolver deviceHandlerMethodArgumentResolver() {
return new DeviceHandlerMethodArgumentResolver();
}
#Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
argumentResolvers.add(deviceHandlerMethodArgumentResolver());
}

spring mybatis transaction getting committed

I am trying to use mybatis spring transaction management
My problem is that the transactions are getting committed even if an exception is thrown.
Relatively new to this, anykind of help is much appreciated.
Following are the code snippets
spring xml configuration
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location">
<value>classpath:Config.properties</value>
</property>
</bean>
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="${db.driver}"/>
<property name="url" value="${db.url}"/>
<property name="username" value="${db.user}"/>
<property name="password" value="${db.pass}"/>
<property name="defaultAutoCommit" value="false" />
</bean>
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<tx:annotation-driven transaction-manager="transactionManager" />
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="configLocation" value="classpath:Configuration.xml" />
<property name="dataSource" ref="dataSource" />
</bean>
<bean class="org.mybatis.spring.SqlSessionTemplate" id="sqlSessionTemplate">
<constructor-arg ref="sqlSessionFactory"/>
</bean>
Service class
#Transactional(rollbackFor=Exception.class, propagation=Propagation.REQUIRED)
public void insertNotes(String noteTypeId,String confidentialValue,String summaryValue,String notes ,String notesId,String noteTypeValue,
String claimNumber,String notepadId,String mode)
{
NotepadExample notepadExample= new NotepadExample();
//to be moved into dao class marked with transaction boundaries
Notepad notepad = new Notepad();
notepad.setAddDate(new Date());
notepad.setAddUser("DummyUser");
if("true".equalsIgnoreCase(confidentialValue))
confidentialValue="Y";
else
confidentialValue="N";
notepad.setConfidentiality(confidentialValue);
Long coverageId=getCoverageId(claimNumber);
notepad.setCoverageId(coverageId);
notepad.setDescription(summaryValue);
notepad.setEditUser("DmyEditUsr");
//notepad.setNotepadId(new Long(4)); //auto sequencing
System.out.println(notes);
notepad.setNotes(notes);
notepad.setNoteType(noteTypeValue); //Do we really need this?
notepad.setNoteTypeId(Long.parseLong(notesId));
if("update".equalsIgnoreCase(mode))
{
notepad.setNotepadId(new Long(notepadId));
notepad.setEditDate(new Date());
notepadMapper.updateByPrimaryKeyWithBLOBs(notepad);
}
else
notepadMapper.insertSelective(notepad);
throw new java.lang.UnsupportedOperationException();
}
Not sure where I am going wrong...
The current call is from the controller as given below
#Controller
public class NotesController {
private static final Logger logger = LoggerFactory
.getLogger(NotesController.class);
#Autowired
private Utils utility;
#Autowired
NotepadService notepadService;
public #ResponseBody List<? extends Object> insertNotes(HttpServletRequest request,
HttpServletResponse response,#RequestParam("noteTypeValue") String noteTypeId,
#RequestParam("confidentialValue")String confidentialValue,
#RequestParam("summaryValue")String summaryValue,
#RequestParam("notes")String notes ,
#RequestParam("notesId")String notesId,
#RequestParam("noteTypeValue")String noteTypeValue,
#RequestParam("claimNumber")String claimNumber,
#RequestParam("notepadId")String notepadId,
#RequestParam("mode")String mode) {
try {
notepadService.insertNotes(noteTypeId, confidentialValue, summaryValue, notes, notesId, noteTypeValue, claimNumber, notepadId, mode);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
}
I had the same issue. I am also relatively new to spring. But according to me it depends on how you are calling your insertNotes() method. If you are calling it from another local method then it will not work, because spring has no way of know that it is called and to start the transaction.
If you are calling it from a method of another class by using autowired object of the class which contains insertNotes() method, then it should work.
For example
class ABC
{
#Autowired
NotesClass notes;
public void testMethod() {
notes.insertNotes();
}
}
class NotesClass
{
#Transactional(rollbackFor=Exception.class, propagation=Propagation.REQUIRED)
public void insertNotes(String noteTypeId,
String confidentialValue,
String summaryValue,String notes ,
String notesId,String noteTypeValue,
String claimNumber,
String notepadId,
String mode) {
//Your code
}
}
You can try using transaction template. Remove #Tranasactional annotation from method and following code to xml file.
<bean id="trTemplate" class="org.springframework.transaction.support.TransactionTemplate">
<property name="timeout" value="30"/>
<property name="transactionManager" ref="transactionManager"/>
</bean>
Create object of Trasactiontemplate and call insertNotes from controller like this
#Autowired
private TransactionTemplate transactionTemplate;
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
#Override
protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {
try {
insertNotes();
} catch (Exception e) {
transactionStatus.setRollbackOnly();
logger.error("Exception ocurred when calling insertNotes", e);
throw new RuntimeException(e);
}
}
});
Note : You have to make all parameters final before calling insertNotes method

Why Spring doesn't intercept transaction?

Tried to configure Spring for tests with hibernate and transactions. Getting bean from app context which is marked with #Transactional transaction isn't intercepted. What I could miss in configuration?
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="configLocation" value="classpath:hibernate.cfg.xml"></property>
<property name="dataSource" ref="dataSource"></property>
</bean>
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<import resource="spring-dao.xml"/>
<tx:annotation-driven transaction-manager="transactionManager" />
<bean id="userService" class="com.test.service.UserServiceimpl">
<property name="userDao" ref="userDao"/>
</bean>
public interface UserService {
public abstract User loadUserById(long userId);
#Transactional
public abstract void doSomething();
}
public class UserServiceimpl implements UserService {
#Override
public void doSomething() {
User user = loadUserById(1);
user.fillUpMoney(999);
userDao.update(user);
throw new RuntimeException("Shpould be rollback");
}
Don't annotate the abstract method as transactional, annotate the concrete implementation.
Do not user BeanFactory ;)
http://forum.springsource.org/showthread.php?122292-Sprinng-doesnt-intercept-transaction

Resources