Getting "no transaction is in progress" when calling em.flush(); - spring-mvc

Hi i am trying to integrate jpa with spring mvc and getting "no transaction is in progress" when trying to call flush() method.
I can make out that something is wrong with transactions even though i have used #Transactional the method is not running in a transaction.
Spring.xml
`<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context"
xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
<!-- Root Context: defines shared resources visible to all other web components -->
<context:annotation-config />
<context:component-scan base-package="com.sushant.mvc" />
<bean class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close" id="dataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://127.0.0.1/mvc" />
<property name="username" value="root" />
<property name="password" value="root" />
<property name="testOnBorrow" value="true" />
<property name="testOnReturn" value="true" />
<property name="testWhileIdle" value="true" />
<property name="timeBetweenEvictionRunsMillis" value="1800000" />
<property name="numTestsPerEvictionRun" value="3" />
<property name="minEvictableIdleTimeMillis" value="1800000" />
<property name="validationQuery" value="SELECT 1" />
<property name="maxActive" value="-1" />
<property name="maxIdle" value="-1" />
<!-- This property should be set to a value so as to support minimum 500
BC concurrent connections. For test, set this value to 5 -->
<property name="initialSize" value="5" />
</bean>
<bean class="org.springframework.orm.jpa.JpaTransactionManager"
id="transactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<tx:annotation-driven mode="proxy" transaction-manager="transactionManager"/>
<bean
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"
id="entityManagerFactory">
<property name="persistenceUnitName" value="persistenceUnit" />
<property name="dataSource" ref="dataSource" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
</property>
<!-- <property name="jpaProperties">
<props>
<prop key="hibernate.hbm2ddl.auto">create</prop>
</props>
</property> -->
</bean>
<bean
class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor">
<property name="defaultPersistenceUnitName" value="persistenceUnit" />
</bean>
<!-- <bean id="user" class="com.sushant.mvc.entities.User"/> -->
</beans>
`
User.java
'
package com.sushant.mvc.entities;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EntityManager;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.PersistenceContext;
import org.springframework.beans.factory.annotation.Configurable;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
#Entity
#Component
#Configurable
public class User {
#PersistenceContext(name = "persistenceUnit")
transient public EntityManager em;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#Column
private String userName;
#Column
private String email;
#Column
private String firstName;
#Column
private String lastName;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public static final EntityManager entityManager() {
EntityManager em = new User().em;
if (em == null)
throw new IllegalStateException(
"Entity manager has not been injected (is the Spring Aspects JAR configured as an AJC/AJDT aspects library?)");
return em;
}
#Transactional
public void save(User user) {
em.persist(user);
em.flush();
}
}
'
HomeController.java
'
package com.sushant.mvc;
import java.text.DateFormat;
import java.util.Date;
import java.util.Locale;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import com.sushant.mvc.entities.User;
/**
* Handles requests for the application home page.
*/
#Controller
public class HomeController {
#Autowired
User user;
private static final Logger logger = LoggerFactory
.getLogger(HomeController.class);
/**
* Simply selects the home view to render by returning its name.
*/
#Transactional
#RequestMapping(value = "/", method = RequestMethod.GET)
public String home(Locale locale, Model model) {
logger.info("Welcome home! the client locale is " + locale.toString());
//user.em.getTransaction().begin();
// User user=new User();
user.setEmail("sushantmahajan05#gmail.com");
user.setFirstName("Sushant");
user.setLastName("Mahajan");
user.setUserName("sushantmahajan05");
user.save(user);
User u=user.em.find(User.class, new Integer(1).longValue());
Date date = new Date();
DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG,
DateFormat.LONG, locale);
String formattedDate = dateFormat.format(date);
model.addAttribute("serverTime", formattedDate);
return "home/home";
}
}
'
servlet-context.xml
'
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<!-- DispatcherServlet Context: defines this servlet's request-processing infrastructure -->
<!-- Enables the Spring MVC #Controller programming model -->
<annotation-driven />
<!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources in the ${webappRoot}/resources directory -->
<resources mapping="/resources/**" location="/resources/" />
<!-- Resolves views selected for rendering by #Controllers to .jsp resources in the /WEB-INF/views directory -->
<beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<beans:property name="prefix" value="/WEB-INF/views/" />
<beans:property name="suffix" value=".jsp" />
</beans:bean>
<context:component-scan base-package="com.sushant.mvc" />
</beans:beans>
'

You may try creating a persistence.xml file .
You can take a look at te following example : JTASessionContext being used with JDBCTransactionFactory; auto-flush will not operate correctly with getCurrentSession()

Related

Spring annotations #NotNull and #Size do not work

I've created a simple page project, which checks a single inputdata field "name" and if it's empty or size is less than 5, it has to show a error-message.
At the moment BindingResult thinks there is no error all the time.
Spring.xml file:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!-- Step 3: Add support for component scanning -->
<context:component-scan base-package="com.mvc" />
<!-- Step 4: Add support for conversion, formatting and validation support -->
<mvc:annotation-driven/>
<!-- Step 5: Define Spring MVC view resolver -->
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/view/" />
<property name="suffix" value=".jsp" />
</bean>
</beans>
Student class:
package com.mvc;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
public class Student {
#NotNull(message = "IsRequired!")
#Size(min = 5, message = "must be greater than 5!")
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Controller:
package com.mvc;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import javax.validation.Valid;
#Controller
public class StudentController {
#RequestMapping("/")
public String showPage(Model model){
model.addAttribute("student", new Student());
return "index";
}
#RequestMapping("/processForm")
public String processForm(
#Valid #ModelAttribute("student") Student student,
BindingResult theBindingResult) {
if (theBindingResult.hasErrors()) {
return "index";
} else {
return "student-confirm";
}
}
}
If required, i can post web.xml, and jsp pages.
Removed previous version of Tomcat(7.0) and installed latest version.

No EntityManager with actual transaction available for current thread - cannot reliably process 'persist' call

No EntityManager with actual transaction available for current thread - cannot reliably process 'persist' call
when I do a test with JUnit, persist method works and I see that my object is inserted, but when I call the method via my Controller doesn't work
here is my Project :
applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:task="http://www.springframework.org/schema/task"
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.2.xsd
http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-4.2.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.1.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.2.xsd">
<!-- <bean id="notification" class="com.app.sqli.notification.NotificationTask" /> -->
<!-- <task:scheduled-tasks> -->
<!-- <task:scheduled ref="notification" method="notifier" cron="*/2 * * * * *"/> -->
<!-- </task:scheduled-tasks> -->
<context:component-scan base-package="com.app.sqli" />
<mvc:annotation-driven />
<bean id="entityManagerFactoryBean" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="packagesToScan" value="com.app.sqli.entities" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
</property>
<property name="jpaProperties">
<props>
<prop key="hibernate.hbm2ddl.auto">validate</prop>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop>
</props>
</property>
</bean>
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/sqli" />
<property name="username" value="root" />
<property name="password" value="" />
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactoryBean" />
</bean>
<tx:annotation-driven />
</beans>
my Model Class:
package com.app.sqli.models;
import javax.persistence.Entity;
import javax.persistence.Id;
#Entity
public class Collaborateur {
#Id
private int id;
private String nom;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getNom() {
return nom;
}
public void setNom(String nom) {
this.nom = nom;
}
}
my DAO Class
package com.app.sqli.dao;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import org.springframework.stereotype.Repository;
import com.app.sqli.models.Collaborateur;
#Repository
public class CollaborateurDao implements IcollaborateurDao{
#PersistenceContext
private EntityManager em;
#Override
public void addCollaborateur(Collaborateur c) {
em.persist(c);
}
}
My Service Class
package com.app.sqli.services;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.app.sqli.dao.IcollaborateurDao;
import com.app.sqli.models.Collaborateur;
#Service
#Transactional
public class CollaborateurService implements IcollaborateurService{
#Autowired
private IcollaborateurDao cdao;
#Override
public void addCollaborateur(Collaborateur c) {
cdao.addCollaborateur(c);
}
}
And My Controller
package com.app.sqli.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import com.app.sqli.models.Collaborateur;
import com.app.sqli.services.IcollaborateurService;
#org.springframework.stereotype.Controller
public class Controller {
#Autowired
private IcollaborateurService cserv;
#RequestMapping(value = "/index")
public String index(Model m) {
System.out.println("insertion ...");
Collaborateur c = new Collaborateur();
c.setId(11);
c.setNom("nom");
cserv.addCollaborateur(c);
return "index";
}
}
thank you #mechkov for your time and help,
My problem is resolved by changing my configuration file, so I have used a Configuration Class with annotations and its works so fine, I still Don't know where the problem was
#Configuration
#ComponentScan(basePackages = "your package")
#EnableTransactionManagement
public class DatabaseConfig {
protected static final String PROPERTY_NAME_DATABASE_DRIVER = "com.mysql.jdbc.Driver";
protected static final String PROPERTY_NAME_DATABASE_PASSWORD = "password";
protected static final String PROPERTY_NAME_DATABASE_URL = "jdbc:mysql://localhost:3306/databasename";
protected static final String PROPERTY_NAME_DATABASE_USERNAME = "login";
private static final String PROPERTY_PACKAGES_TO_SCAN = "where your models are";
#Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactoryBean(DataSource dataSource, JpaVendorAdapter jpaVendorAdapter){
LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean();
entityManagerFactoryBean.setDataSource(dataSource);
entityManagerFactoryBean.setJpaVendorAdapter(jpaVendorAdapter);
entityManagerFactoryBean.setPackagesToScan(PROPERTY_PACKAGES_TO_SCAN);
return entityManagerFactoryBean;
}
#Bean
public BasicDataSource dataSource(){
BasicDataSource ds = new BasicDataSource();
ds.setDriverClassName(PROPERTY_NAME_DATABASE_DRIVER);
ds.setUrl(PROPERTY_NAME_DATABASE_URL);
ds.setUsername(PROPERTY_NAME_DATABASE_USERNAME);
ds.setPassword(PROPERTY_NAME_DATABASE_PASSWORD);
ds.setInitialSize(5);
return ds;
}
#Bean
public JpaVendorAdapter jpaVendorAdapter(){
HibernateJpaVendorAdapter adapter = new HibernateJpaVendorAdapter();
adapter.setDatabase(Database.MYSQL);
adapter.setShowSql(true);
adapter.setGenerateDdl(true);
//I'm using MySQL5InnoDBDialect to make my tables support foreign keys
adapter.setDatabasePlatform("org.hibernate.dialect.MySQL5InnoDBDialect");
return adapter;
}
#Bean
public PlatformTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) {
return new JpaTransactionManager(entityManagerFactory);
}
}
I do not know if anyone who is reading this (today) has the same case as mine, but I had the same problem. Luckly, I could fix it by simply putting the following in my spring-conf.xml:
<beans xmlns="http://www.springframework.org/schema/beans"
...
xmlns:tx="http://www.springframework.org/schema/tx"
...
xsi:schemaLocation="
...
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
<bean id="tManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="emf" />
</bean>
<!-- This does the trick! -->
<tx:annotation-driven transaction-manager="tManager" />
Note: I'm using declarative transactions through annotations. So, if you do, annotating your method with #Transactional can also solve your problem.
REFERENCE:
http://blog.jhades.org/how-does-spring-transactional-really-work/
http://docs.spring.io/spring-framework/docs/current/spring-framework-reference/html/transaction.html
Just to confirm, that adding last bean definition solves this issue !
My config class is as below :
#Configuration
#EnableTransactionManagement
#ComponentScan
public class OFSConfig {
#Bean
public IDAO<FuelStation> getFSService() {
return new FSService();
}
#Bean
public LocalEntityManagerFactoryBean emfBean() {
LocalEntityManagerFactoryBean e = new LocalEntityManagerFactoryBean();
e.setPersistenceUnitName("org.superbapps.db_OWSDB_PU");
return e;
}
#Bean
public PlatformTransactionManager transactionManager(EntityManagerFactory em) {
return new JpaTransactionManager(em);
}
}
The service itself is as follows :
#Transactional
#Repository
public class FSService implements IDAO<FuelStation> {
#PersistenceContext
private EntityManager EM;
public EntityManager getEM() {
return EM;
}
public void setEM(EntityManager EM) {
this.EM = EM;
}
#Override
public List<FuelStation> getAll() {
return EM.createNamedQuery("FuelStation.findAll")
.getResultList();
}
#Override
public FuelStation getByID(String ID) {
FuelStation fs = (FuelStation) EM.createNamedQuery("FuelStation.findById")
.setParameter("id", ID)
.getSingleResult();
return fs;
}
#Override
public void update(FuelStation entity) {
EM.merge(entity);
}
}

Who implemente the spring BindingResult?

I'm new to Spring MVC and I'm trying to understand the following code
package com.companyname.springapp.web;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.companyname.springapp.service.PriceIncrease;
import com.companyname.springapp.service.ProductManager;
#Controller
#RequestMapping(value="/priceincrease.htm")
public class PriceIncreaseFormController {
/** Logger for this class and subclasses */
protected final Log logger = LogFactory.getLog(getClass());
#Autowired
private ProductManager productManager;
#RequestMapping(method = RequestMethod.POST)
public String onSubmit(#Valid PriceIncrease priceIncrease, BindingResult result)
{
if (result.hasErrors()) {
return "priceincrease";
}
int increase = priceIncrease.getPercentage();
logger.info("Increasing prices by " + increase + "%.");
productManager.increasePrice(increase);
return "redirect:/hello.htm";
}
#RequestMapping(method = RequestMethod.GET)
protected PriceIncrease formBackingObject(HttpServletRequest request) throws ServletException {
PriceIncrease priceIncrease = new PriceIncrease();
priceIncrease.setPercentage(15);
return priceIncrease;
}
public void setProductManager(ProductManager productManager) {
this.productManager = productManager;
}
public ProductManager getProductManager() {
return productManager;
}
}
As far as I know the BindingResult is an interface and the onSubmit method receives a BindingResult object. What I don't understand is: Who implemented this interface to create the object and where is that implementation?
Here is the servlet xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<bean id="productManager" class="com.companyname.springapp.service.SimpleProductManager">
<property name="products">
<list>
<ref bean="product1"/>
<ref bean="product2"/>
<ref bean="product3"/>
</list>
</property>
</bean>
<bean id="product1" class="com.companyname.springapp.domain.Product">
<property name="description" value="Lamp"/>
<property name="price" value="5.75"/>
</bean>
<bean id="product2" class="com.companyname.springapp.domain.Product">
<property name="description" value="Table"/>
<property name="price" value="75.25"/>
</bean>
<bean id="product3" class="com.companyname.springapp.domain.Product">
<property name="description" value="Chair"/>
<property name="price" value="22.79"/>
</bean>
<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basename" value="messages"/>
</bean>
<!-- Scans the classpath of this application for #Components to deploy as beans -->
<context:component-scan base-package="com.companyname.springapp.web" />
<!-- Configures the #Controller programming model -->
<mvc:annotation-driven/>
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView"></property>
<property name="prefix" value="/WEB-INF/views/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
</beans>
I don't if this helps but I'm using Tomcat 7.0 and whole code is in here: http://docs.spring.io/docs/Spring-MVC-step-by-step/
Who implemented this interface to create the object and where is that implementation?
Implemented in the Spring framework and instantiated by your context.
In the above example BeanPropertyBindingResult.class is exact implementation of BindingResult instantiated
http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/validation/BeanPropertyBindingResult.html

Bootstrap with Spring MVC

I am trying to use bootstrap to style my app but I won't apply the styles. This is what is in my JSP
<c:url value="css/bootstrap.min.css" var="cssBoostrap" />
<link href="${cssBootstrap}" rel="stylesheet">
This css folder is on the same level as WEB-INF not inside of it but it won't work if it is inside of it or even if the files are inside of the view dir. What could the problem possibly be? I no longer get the no mapping error when adding the mapping to my servlet.xml but yet it still doesn't see the file or I can assume it doesn't because no styling is applied, then I change it to link to the online hosted version and all my styles are applied correctly.
Servlet XML
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd">
<!-- Scans for annotated #Controllers in the classpath -->
<context:component-scan base-package="com.eaglecrk.recognition" />
<mvc:annotation-driven />
<bean
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:properties/system.properties</value>
</list>
</property>
</bean>
<!-- messageSource -->
<bean id="messageSource"
class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<property name="basenames">
<list>
<value>file:${external.property.directory}PMS.EOTM.SendEmail</value>
</list>
</property>
</bean>
<!-- dataSource -->
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<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>
<!-- session factory -->
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource">
<ref bean="dataSource" />
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">${hibernate.dialect}</prop>
<prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
<prop key="hibernate.cache.use_second_level_cache">${hibernate.cache.use_second_level_cache}</prop>
<prop key="hibernate.cache.use_query_cache">${hibernate.cache.use_query_cache}</prop>
<prop key="hibernate.cache.provider_class">${hibernate.cache.provider_class}</prop>
</props>
</property>
<property name="packagesToScan" value="com.eaglecrk.recognition.persistence" />
</bean>
<!-- Transaction Manager -->
<bean id="transactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager" />
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/views/" />
<property name="suffix" value=".jsp" />
</bean>
<bean id="javaMailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl">
<property name="host" value = "${email.host}" />
<property name="port" value="${email.port}" />
<property name="username" value="${email.username}" />
<property name="password" value="${email.password}" />
<property name="javaMailProperties">
<props>
<prop key="mail.smtp.ssl.trust">${email.mail.smtp.ssl.trust}</prop>
<prop key="mail.smtp.starttls.enable">${email.mail.smtp.starttls.enable}</prop>
<prop key="mail.smtp.auth">${email.mail.smtp.auth}</prop>
</props>
</property>
</bean>
</beans>
Controller
package com.eaglecrk.recognition.controller;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.context.MessageSourceAware;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.ui.ModelMap;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;
import com.eaglecrk.recognition.dao.award.AwardDao;
import com.eaglecrk.recognition.dao.award.AwardDaoInterface;
import com.eaglecrk.recognition.dao.employee.EmployeeDaoInterface;
import com.eaglecrk.recognition.model.AwardTypeModel;
import com.eaglecrk.recognition.model.EmployeeModel;
import com.eaglecrk.recognition.persistence.AwardNomination;
import com.eaglecrk.recognition.persistence.AwardType;
import com.eaglecrk.recognition.persistence.Employee;
import com.eaglecrk.recognition.util.Functions;
import com.eaglecrk.recognition.util.SpringMailSender;
#Controller
public class TestController extends BaseController implements MessageSourceAware {
private static final Logger LOG = LogManager
.getLogger(TestController.class);
#Autowired
private EmployeeDaoInterface employeeDao;
#Autowired
private AwardDaoInterface awardDao;
#Autowired
private SpringMailSender springMailSender;
/**
* #param request
* #return (ModelAndView) object
*/
#RequestMapping(value = "/test", method = RequestMethod.GET)
public ModelAndView test() {
try {
LOG.info("Entered the controller");
springMailSender.sendMail();
} catch (Exception e) {
e.printStackTrace();
}
ModelAndView mav = new ModelAndView();
ArrayList<String> names = new ArrayList<String>();
List<Employee> employees = employeeDao.findAll();
Collections.sort(employees, Functions.lastNameOrder);
for (Employee employee : employees) {
EmployeeModel model = new EmployeeModel(employee);
names.add(model.getLocation().getLocationId() + " " +
model.getFirstName() + " " + model.getLastName());
}
mav.addObject("names", names);
mav.setViewName("test");
return mav;
}
#RequestMapping(value = "/test", method = RequestMethod.POST)
public void addNomination(
#ModelAttribute("SpringWeb") AwardNomination nomination,
ModelMap model) {
}
#RequestMapping(value = "/login", method = RequestMethod.GET)
public ModelAndView login() {
ModelAndView mav = new ModelAndView();
mav.setViewName("login");
return mav;
}
#RequestMapping(value="/newAwardType", method=RequestMethod.GET)
public ModelAndView addAward() {
ModelAndView mav = new ModelAndView();
ArrayList<AwardTypeModel> models = new ArrayList<AwardTypeModel>();
try{
AwardTypeModel newAwardTypeModel = new AwardTypeModel();
newAwardTypeModel.setActive(false);
newAwardTypeModel.setName("AwardTypeModel.name");
newAwardTypeModel.setDescription("AwardTypeModel.description");
// newAwardTypeModel.setId(123456);
newAwardTypeModel.setCreated(new Date());
newAwardTypeModel.setModified(new Date());
models.add(newAwardTypeModel);
} catch (Exception e){
e.printStackTrace();
}
mav.addObject("awardTypes", models);
mav.addObject("model", new AwardTypeModel());
mav.setViewName("addAward");
return mav;
}
#RequestMapping(value="/addAward", method=RequestMethod.POST)
public String addAwardForm(#ModelAttribute("model") AwardTypeModel model, BindingResult result){
model.setCreated(new Date());
model.setModified(new Date());
AwardType dbo = (AwardType) model.convertToDb();
awardDao.save(dbo);
return "redirect:/test";
}
#Override
public void setMessageSource(MessageSource messageSource) {
// TODO Auto-generated method stub
}
}
Create one folder by name resources at same level as WEB-INF as shown below:
WebApp-|
| - resources -|
| |-styles-|
| | |-bootstrap.min.css
| |
| |-javascript-|
| |-example.js
|
| - WEB-INF
Include the following line in your servlet xml:
<mvc:resources mapping="/resources/**" location="/resources/"/>
Access these resources in your jsp as:
<%#taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<html>
<head>
<link href="<c:url value="/resources/styles/bootstrap.min.css" />" rel="stylesheet">
<script src="<c:url value="/resources/javascript/example.js" />"></script>
....
You should declare in your dispatcher servlet config the location of you resources (e.g js, css, img etc.) :
<mvc:resources mapping="/public/**" location="/public/" />
location contains the path to your resources folder. mapping is how you call your resources in your jsp.
Don't forget to declare your mvc namespace in dispatcher config.
Following Prasads Answer above if you need Java based configuration for the same use -
#Configuration
#ComponentScan("com.eaglecrk.recognition")
#EnableWebMvc
public class SpringConfig extends WebMvcConfigurerAdapter {
#Bean
public UrlBasedViewResolver setupViewResolver() {
UrlBasedViewResolver resolver = new UrlBasedViewResolver();
resolver.setPrefix("/WEB-INF/jsp/");
resolver.setSuffix(".jsp");
resolver.setViewClass(JstlView.class);
return resolver;
}
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");
}
#Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
}
Also if you are using xml based configuration don't forget <mvc:default-servlet-handler/>

Spring MVC Content Negotiation with HttpMessageConverter

For a recent project we wanted to support XML and another format for our resopnses.
However, we could not control the Accept header. Hence we configured a ContentNegotiatingViewResolver to use a request parameter instead:
<bean id="viewResolver" class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
<property name="favorParameter" value="true" />
<property name="parameterName" value="format" />
<property name="ignoreAcceptHeader" value="true" />
<property name="defaultContentType" value="application/xml" />
<property name="mediaTypes">
<map>
<entry key="xml" value="application/xml" />
<entry key="foo" value="application/x-foo" />
</map>
</property>
<property name="viewResolvers">
<list>
<bean class="org.springframework.web.servlet.view.ResourceBundleViewResolver" >
<property name="basename" value="views-xml" />
</bean>
<bean class="org.springframework.web.servlet.view.ResourceBundleViewResolver" >
<property name="basename" value="views-foo" />
</bean>
</list>
</property>
</bean>
Now however, I was wondering if I could move to using #ResponseBody and HttpMessageConverter implementations to simplify the amount of code I need to maintain.
However, is there a similar way to ensure that a reqeust parameter is used for content negotiation, instead of the Accept header?
There is a workaround, as described at https://jira.springframework.org/browse/SPR-7517
Create a subclass of AnnotationMethodHandlerAdapter:
package org.nkl.spring;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpInputMessage;
import org.springframework.http.MediaType;
import org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter;
public class MyAnnotationMethodHandlerAdapter extends AnnotationMethodHandlerAdapter {
private Logger logger = LoggerFactory.getLogger(MyAnnotationMethodHandlerAdapter.class);
private String requestParam = "accept";
private Map<String, MediaType> mediaTypesMap;
#Override protected HttpInputMessage createHttpInputMessage(HttpServletRequest request) throws Exception {
HttpInputMessage message = super.createHttpInputMessage(request);
String accept = request.getParameter(requestParam);
if (accept == null || accept.isEmpty()) {
logger.info(String.format("Request parameter [%s] not found. Using standard HttpInputMessage", requestParam));
return message;
} else {
logger.info(String.format("Request parameter [%s] was [%s]", requestParam, accept));
MediaType mediaType = mediaTypesMap.get(accept);
if (mediaType == null) {
logger.info(String.format("Suitable MediaType not found. Using standard HttpInputMessage"));
return message;
} else {
logger.info(String.format("Suitable MediaType [%s] found. Using custom HttpInputMessage", mediaType));
return new MyHttpInputMessage(message, mediaTypesMap.get(accept));
}
}
}
public void setMediaTypesMap(Map<String, MediaType> mediaTypesMap) {
this.mediaTypesMap = mediaTypesMap;
}
public void setRequestParam(String requestParam) {
this.requestParam = requestParam;
}
}
Create a Decorator of HttpInputMessage:
package org.nkl.spring;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpInputMessage;
import org.springframework.http.MediaType;
public class MyHttpInputMessage implements HttpInputMessage {
private HttpInputMessage delegate;
public MyHttpInputMessage(HttpInputMessage delagate, MediaType mediaType) {
this.delegate = delagate;
this.delegate.getHeaders().setAccept(Arrays.asList(mediaType));
}
#Override public InputStream getBody() throws IOException {
return this.delegate.getBody();
}
#Override public HttpHeaders getHeaders() {
return this.delegate.getHeaders();
}
}
Configure your bean like:
<bean class="org.nkl.spring.MyAnnotationMethodHandlerAdapter">
<property name="requestParam" value="format" />
<property name="mediaTypesMap">
<util:map>
<entry key="plain" value="text/plain" />
<entry key="xml" value="text/xml" />
</util:map>
</property>
<property name="messageConverters">
<util:list>
... converters go here ...
</util:list>
</property>
</bean>
Newer versions of Spring can now do this. The ContentNegotiationManagerFactoryBean can create a content negotiation manager that does precisely what you want here. See my answer to a related question.

Resources