Spring 4 MVC+Hibernate Many-to-many JSP Example with annotation

This post demonstrates Hibernate Many-to-many example, with join table in Spring MVC CRUD Web application. We will discuss managing Many-to-Many relationship both in views and back-end. We will perform Create, Update, Delete & Query all using application Web interface.

This posts makes use of Springorg.springframework.core.convert.converter.Converter interface, which helps us with mapping Id’s of items to actual entities in database.

SpringMVCHibernateManyToManyCRUDExample_img8

SpringMVCHibernateManyToManyCRUDExample_img3_1

Complete example with detailed explanation is presented below.


Following technologies being used:

  • Spring 4.1.7.RELEASE
  • Hibernate Core 4.3.10.Final
  • validation-api 1.1.0.Final
  • hibernate-validator 5.1.3.Final
  • MySQL Server 5.6
  • Maven 3
  • JDK 1.7
  • Tomcat 8.0.21
  • Eclipse JUNO Service Release 2

Let’s begin.

Step 1. Create schema for Many-To-Many association with Join table

SpringMVCHibernateManyToManyCRUDExample_schema_img1

APP_USER : Contains Users. A User can have several profiles[ USER,ADMIN,DBA].
USER_PROFILE : Contains User Profiles. A Profile can be linked to several users.
APP_USER_USER_PROFILE : It’s a Join table linking APP_USER & USER_PROFILE in Many-To-Many relationship.

For demonstration purpose, We will discuss Many-to-Many unidirectional [User to UserProfile] setup in this example.

create table APP_USER (
   id BIGINT NOT NULL AUTO_INCREMENT,
   sso_id VARCHAR(30) NOT NULL,
   password VARCHAR(100) NOT NULL,
   first_name VARCHAR(30) NOT NULL,
   last_name  VARCHAR(30) NOT NULL,
   email VARCHAR(30) NOT NULL,
   PRIMARY KEY (id),
   UNIQUE (sso_id)
);
 
 
create table USER_PROFILE(
   id BIGINT NOT NULL AUTO_INCREMENT,
   type VARCHAR(30) NOT NULL,
   PRIMARY KEY (id),
   UNIQUE (type)
);
 
 
CREATE TABLE APP_USER_USER_PROFILE (
    user_id BIGINT NOT NULL,
    user_profile_id BIGINT NOT NULL,
    PRIMARY KEY (user_id, user_profile_id),
    CONSTRAINT FK_APP_USER FOREIGN KEY (user_id) REFERENCES APP_USER (id),
    CONSTRAINT FK_USER_PROFILE FOREIGN KEY (user_profile_id) REFERENCES USER_PROFILE (id)
);

/* Populate USER_PROFILE Table */
INSERT INTO USER_PROFILE(type)
VALUES ('USER');
 
INSERT INTO USER_PROFILE(type)
VALUES ('ADMIN');
 
INSERT INTO USER_PROFILE(type)
VALUES ('DBA');

commit;

For any help with MySQL & database setup , please visit MySQL installation on Local PC.

Step 2: Create the directory structure

Following will be the final project structure:

SpringMVCHibernateManyToManyCRUDExample_img00
SpringMVCHibernateManyToManyCRUDExample_img01

Step 3: Update pom.xml to include required dependencies

<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
	xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

	<modelVersion>4.0.0</modelVersion>
	<groupId>com.websystique.springmvc</groupId>
	<artifactId>SpringMVCHibernateManyToManyCRUDExample</artifactId>
	<packaging>war</packaging>
	<version>1.0.0</version>
	<name>SpringMVCHibernateManyToManyCRUDExample</name>

  	<properties>
		<springframework.version>4.1.7.RELEASE</springframework.version>
		<hibernate.version>4.3.10.Final</hibernate.version>
		<mysql.connector.version>5.1.31</mysql.connector.version>
	</properties>

	<dependencies>
		<!-- Spring -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-core</artifactId>
			<version>${springframework.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-web</artifactId>
			<version>${springframework.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-webmvc</artifactId>
			<version>${springframework.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-tx</artifactId>
			<version>${springframework.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-orm</artifactId>
			<version>${springframework.version}</version>
		</dependency>

		<!-- Hibernate -->
		<dependency>
			<groupId>org.hibernate</groupId>
			<artifactId>hibernate-core</artifactId>
			<version>${hibernate.version}</version>
		</dependency>

		<!-- jsr303 validation -->
		<dependency>
			<groupId>javax.validation</groupId>
			<artifactId>validation-api</artifactId>
			<version>1.1.0.Final</version>
		</dependency>
		<dependency>
			<groupId>org.hibernate</groupId>
			<artifactId>hibernate-validator</artifactId>
			<version>5.1.3.Final</version>
		</dependency>

		<!-- MySQL -->
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<version>${mysql.connector.version}</version>
		</dependency>

		<!-- Servlet+JSP+JSTL -->
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>javax.servlet-api</artifactId>
			<version>3.1.0</version>
		</dependency>
		<dependency>
			<groupId>javax.servlet.jsp</groupId>
			<artifactId>javax.servlet.jsp-api</artifactId>
			<version>2.3.1</version>
		</dependency>
		<dependency>
		    <groupId>javax.servlet</groupId>
		    <artifactId>jstl</artifactId>
		    <version>1.2</version>
		</dependency>
		
	</dependencies>

	<build>
		<pluginManagement>
			<plugins>
				<plugin>
					<groupId>org.apache.maven.plugins</groupId>
					<artifactId>maven-compiler-plugin</artifactId>
					<version>3.2</version>
					<configuration>
						<source>1.7</source>
						<target>1.7</target>
					</configuration>
				</plugin>
				<plugin>
					<groupId>org.apache.maven.plugins</groupId>
					<artifactId>maven-war-plugin</artifactId>
					<version>2.4</version>
					<configuration>
						<warSourceDirectory>src/main/webapp</warSourceDirectory>
						<warName>SpringMVCHibernateManyToManyCRUDExample</warName>
						<failOnMissingWebXml>false</failOnMissingWebXml>
					</configuration>
				</plugin>
			</plugins>
		</pluginManagement>
		<finalName>SpringMVCHibernateManyToManyCRUDExample</finalName>
	</build>
</project>

Step 4. Prepare Model classes

package com.websystique.springmvc.model;

import java.util.HashSet;
import java.util.Set;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.Table;

import org.hibernate.validator.constraints.NotEmpty;

@Entity
@Table(name="APP_USER")
public class User {

	@Id @GeneratedValue(strategy=GenerationType.IDENTITY)
	private Integer id;

	@NotEmpty
	@Column(name="SSO_ID", unique=true, nullable=false)
	private String ssoId;
	
	@NotEmpty
	@Column(name="PASSWORD", nullable=false)
	private String password;
		
	@NotEmpty
	@Column(name="FIRST_NAME", nullable=false)
	private String firstName;

	@NotEmpty
	@Column(name="LAST_NAME", nullable=false)
	private String lastName;

	@NotEmpty
	@Column(name="EMAIL", nullable=false)
	private String email;

	@NotEmpty
	@ManyToMany(fetch = FetchType.LAZY)
	@JoinTable(name = "APP_USER_USER_PROFILE", 
             joinColumns = { @JoinColumn(name = "USER_ID") }, 
             inverseJoinColumns = { @JoinColumn(name = "USER_PROFILE_ID") })
	private Set<UserProfile> userProfiles = new HashSet<UserProfile>();

	public Integer getId() {
		return id;
	}

	public void setId(Integer id) {
		this.id = id;
	}

	public String getSsoId() {
		return ssoId;
	}

	public void setSsoId(String ssoId) {
		this.ssoId = ssoId;
	}

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	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 String getEmail() {
		return email;
	}

	public void setEmail(String email) {
		this.email = email;
	}

	public Set<UserProfile> getUserProfiles() {
		return userProfiles;
	}

	public void setUserProfiles(Set<UserProfile> userProfiles) {
		this.userProfiles = userProfiles;
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((id == null) ? 0 : id.hashCode());
		result = prime * result + ((ssoId == null) ? 0 : ssoId.hashCode());
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (!(obj instanceof User))
			return false;
		User other = (User) obj;
		if (id == null) {
			if (other.id != null)
				return false;
		} else if (!id.equals(other.id))
			return false;
		if (ssoId == null) {
			if (other.ssoId != null)
				return false;
		} else if (!ssoId.equals(other.ssoId))
			return false;
		return true;
	}

	@Override
	public String toString() {
		return "User [id=" + id + ", ssoId=" + ssoId + ", password=" + password
				+ ", firstName=" + firstName + ", lastName=" + lastName
				+ ", email=" + email + "]";
	}

}

Look at how userProfiles property is annotated with ManyToMany.

@ManyToMany indicates that there is a Many-to-Many relationship between User and UserProfile. A User can have several profiles [ USER, ADMIN, DBA] while a profile can belong to several users. @JoinTable indicates that there is a link table which joins two tables using foreign key constraints to their primary keys. This annotation is mainly used on the owning side of the relationship. joinColumns refers to the column name of owning side(ID of USER), and inverseJoinColumns refers to the column of inverse side of relationship(ID of USER_PROFILE). Primary key of this joined table is combination of USER_ID & USER_PROFILE_ID.

Lazy Loading:
Pay special attention to fetch = FetchType.LAZY. Here we are informing hibernate to lazy load the userProfile collection. It’s also the default behavior. With this setup, a query to load the collection will be fired only when it is first accessed. It’s a good way to avoid fetching all connected object graph which is an expensive operation. When you are in transaction/active session, and will try to access collection, hibernate will fire separate select to fetch them.

But if you are outside active session (session closed/no transaction :you are in JSP e.g.), and tried to access the collection, you will meet your nemesis : org.hibernate.LazyInitializationException – could not initialize proxy – no Session. To avoid it, you need to initialize the collection on demand by calling Hibernate.initialize(user.getUserProfiles()); within an active session [you know the DAO method you were in, before coming all the way to view, you may call this initialize in that method.]

Also note that we are not using any cascade. It is because a userprofile is not dependent of user, and can live independently.


One important remark : In case of *Many* association, always override hashcode and equals method which are looked by hibernate when holding entities into collections.

package com.websystique.springmvc.model;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name="USER_PROFILE")
public class UserProfile {

	@Id @GeneratedValue(strategy=GenerationType.IDENTITY)
	private Integer id;	

	@Column(name="TYPE", length=15, unique=true, nullable=false)
	private String type = UserProfileType.USER.getUserProfileType();
	
	public Integer getId() {
		return id;
	}

	public void setId(Integer id) {
		this.id = id;
	}

	public String getType() {
		return type;
	}

	public void setType(String type) {
		this.type = type;
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((id == null) ? 0 : id.hashCode());
		result = prime * result + ((type == null) ? 0 : type.hashCode());
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (!(obj instanceof UserProfile))
			return false;
		UserProfile other = (UserProfile) obj;
		if (id == null) {
			if (other.id != null)
				return false;
		} else if (!id.equals(other.id))
			return false;
		if (type == null) {
			if (other.type != null)
				return false;
		} else if (!type.equals(other.type))
			return false;
		return true;
	}

	@Override
	public String toString() {
		return "UserProfile [id=" + id + ", type=" + type + "]";
	}

}

Since we are showing unidirectional relationship(User to UserProfile), no need to refer User in UserProfile.

package com.websystique.springmvc.model;

public enum UserProfileType {
	USER("USER"),
	DBA("DBA"),
	ADMIN("ADMIN");
	
	String userProfileType;
	
	private UserProfileType(String userProfileType){
		this.userProfileType = userProfileType;
	}
	
	public String getUserProfileType(){
		return userProfileType;
	}
	
}

Step 5. Create DAO layer

package com.websystique.springmvc.dao;

import java.util.List;

import com.websystique.springmvc.model.User;


public interface UserDao {

	User findById(int id);
	
	User findBySSO(String sso);
	
	void save(User user);
	
	void deleteBySSO(String sso);
	
	List<User> findAllUsers();

}
package com.websystique.springmvc.dao;

import java.util.List;

import com.websystique.springmvc.model.UserProfile;


public interface UserProfileDao {

	List<UserProfile> findAll();
	
	UserProfile findByType(String type);
	
	UserProfile findById(int id);
}
package com.websystique.springmvc.dao;

import java.io.Serializable;

import java.lang.reflect.ParameterizedType;

import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;

public abstract class AbstractDao<PK extends Serializable, T> {
	
	private final Class<T> persistentClass;
	
	@SuppressWarnings("unchecked")
	public AbstractDao(){
		this.persistentClass =(Class<T>) ((ParameterizedType) this.getClass().getGenericSuperclass

()).getActualTypeArguments()[1];
	}
	
	@Autowired
	private SessionFactory sessionFactory;

	protected Session getSession(){
		return sessionFactory.getCurrentSession();
	}

	@SuppressWarnings("unchecked")
	public T getByKey(PK key) {
		return (T) getSession().get(persistentClass, key);
	}

	public void persist(T entity) {
		getSession().persist(entity);
	}

	public void delete(T entity) {
		getSession().delete(entity);
	}
	
	protected Criteria createEntityCriteria(){
		return getSession().createCriteria(persistentClass);
	}

}
package com.websystique.springmvc.dao;

import java.util.List;

import org.hibernate.Criteria;
import org.hibernate.Hibernate;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;
import org.springframework.stereotype.Repository;

import com.websystique.springmvc.model.User;



@Repository("userDao")
public class UserDaoImpl extends AbstractDao<Integer, User> implements UserDao {

	public User findById(int id) {
		User user = getByKey(id);
		if(user!=null){
			Hibernate.initialize(user.getUserProfiles());
		}
		return user;
	}

	public User findBySSO(String sso) {
		System.out.println("SSO : "+sso);
		Criteria crit = createEntityCriteria();
		crit.add(Restrictions.eq("ssoId", sso));
		User user = (User)crit.uniqueResult();
		if(user!=null){
			Hibernate.initialize(user.getUserProfiles());
		}
		return user;
	}

	@SuppressWarnings("unchecked")
	public List<User> findAllUsers() {
		Criteria criteria = createEntityCriteria().addOrder(Order.asc("firstName"));
		criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);//To avoid duplicates.
		List<User> users = (List<User>) criteria.list();
		
		// No need to fetch userProfiles since we are not showing them on list page. Let them lazy load. 
		// Uncomment below lines for eagerly fetching of userProfiles if you want.
		/*
		for(User user : users){
			Hibernate.initialize(user.getUserProfiles());
		}*/
		return users;
	}

	public void save(User user) {
		persist(user);
	}

	public void deleteBySSO(String sso) {
		Criteria crit = createEntityCriteria();
		crit.add(Restrictions.eq("ssoId", sso));
		User user = (User)crit.uniqueResult();
		delete(user);
	}

}
package com.websystique.springmvc.dao;

import java.util.List;

import org.hibernate.Criteria;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;
import org.springframework.stereotype.Repository;

import com.websystique.springmvc.model.UserProfile;



@Repository("userProfileDao")
public class UserProfileDaoImpl extends AbstractDao<Integer, UserProfile>implements UserProfileDao{

	public UserProfile findById(int id) {
		return getByKey(id);
	}

	public UserProfile findByType(String type) {
		Criteria crit = createEntityCriteria();
		crit.add(Restrictions.eq("type", type));
		return (UserProfile) crit.uniqueResult();
	}
	
	@SuppressWarnings("unchecked")
	public List<UserProfile> findAll(){
		Criteria crit = createEntityCriteria();
		crit.addOrder(Order.asc("type"));
		return (List<UserProfile>)crit.list();
	}
	
}

Step 6. Create Service layer

package com.websystique.springmvc.service;

import java.util.List;

import com.websystique.springmvc.model.UserProfile;


public interface UserProfileService {

	UserProfile findById(int id);

	UserProfile findByType(String type);
	
	List<UserProfile> findAll();
	
}
package com.websystique.springmvc.service;

import java.util.List;

import com.websystique.springmvc.model.User;


public interface UserService {
	
	User findById(int id);
	
	User findBySSO(String sso);
	
	void saveUser(User user);
	
	void updateUser(User user);
	
	void deleteUserBySSO(String sso);

	List<User> findAllUsers(); 
	
	boolean isUserSSOUnique(Integer id, String sso);

}
package com.websystique.springmvc.service;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.websystique.springmvc.dao.UserProfileDao;
import com.websystique.springmvc.model.UserProfile;


@Service("userProfileService")
@Transactional
public class UserProfileServiceImpl implements UserProfileService{
	
	@Autowired
	UserProfileDao dao;
	
	public UserProfile findById(int id) {
		return dao.findById(id);
	}

	public UserProfile findByType(String type){
		return dao.findByType(type);
	}

	public List<UserProfile> findAll() {
		return dao.findAll();
	}
}
package com.websystique.springmvc.service;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.websystique.springmvc.dao.UserDao;
import com.websystique.springmvc.model.User;


@Service("userService")
@Transactional
public class UserServiceImpl implements UserService{

	@Autowired
	private UserDao dao;

	public User findById(int id) {
		return dao.findById(id);
	}

	public User findBySSO(String sso) {
		User user = dao.findBySSO(sso);
		return user;
	}

	public void saveUser(User user) {
		dao.save(user);
	}

	/*
	 * Since the method is running with Transaction, No need to call hibernate update explicitly.
	 * Just fetch the entity from db and update it with proper values within transaction.
	 * It will be updated in db once transaction ends. 
	 */
	public void updateUser(User user) {
		User entity = dao.findById(user.getId());
		if(entity!=null){
			entity.setSsoId(user.getSsoId());
			entity.setPassword(user.getPassword());
			entity.setFirstName(user.getFirstName());
			entity.setLastName(user.getLastName());
			entity.setEmail(user.getEmail());
			entity.setUserProfiles(user.getUserProfiles());
		}
	}

	
	public void deleteUserBySSO(String sso) {
		dao.deleteBySSO(sso);
	}

	public List<User> findAllUsers() {
		return dao.findAllUsers();
	}

	public boolean isUserSSOUnique(Integer id, String sso) {
		User user = findBySSO(sso);
		return ( user == null || ((id != null) && (user.getId() == id)));
	}
	
}

Step 7. Create Hibernate Configuration

package com.websystique.springmvc.configuration;

import java.util.Properties;

import javax.sql.DataSource;

import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.orm.hibernate4.HibernateTransactionManager;
import org.springframework.orm.hibernate4.LocalSessionFactoryBean;
import org.springframework.transaction.annotation.EnableTransactionManagement;

@Configuration
@EnableTransactionManagement
@ComponentScan({ "com.websystique.springmvc.configuration" })
@PropertySource(value = { "classpath:application.properties" })
public class HibernateConfiguration {

    @Autowired
    private Environment environment;

    @Bean
    public LocalSessionFactoryBean sessionFactory() {
        LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
        sessionFactory.setDataSource(dataSource());
        sessionFactory.setPackagesToScan(new String[] { "com.websystique.springmvc.model" });
        sessionFactory.setHibernateProperties(hibernateProperties());
        return sessionFactory;
     }
	
    @Bean
    public DataSource dataSource() {
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setDriverClassName(environment.getRequiredProperty("jdbc.driverClassName"));
        dataSource.setUrl(environment.getRequiredProperty("jdbc.url"));
        dataSource.setUsername(environment.getRequiredProperty("jdbc.username"));
        dataSource.setPassword(environment.getRequiredProperty("jdbc.password"));
        return dataSource;
    }
    
    private Properties hibernateProperties() {
        Properties properties = new Properties();
        properties.put("hibernate.dialect", environment.getRequiredProperty("hibernate.dialect"));
        properties.put("hibernate.show_sql", environment.getRequiredProperty("hibernate.show_sql"));
        properties.put("hibernate.format_sql", environment.getRequiredProperty("hibernate.format_sql"));
        return properties;        
    }
    
	@Bean
    @Autowired
    public HibernateTransactionManager transactionManager(SessionFactory s) {
       HibernateTransactionManager txManager = new HibernateTransactionManager();
       txManager.setSessionFactory(s);
       return txManager;
    }
}

Above Hibernate configuration uses below mentioned application.properties

jdbc.driverClassName = com.mysql.jdbc.Driver
jdbc.url = jdbc:mysql://localhost:3306/websystique
jdbc.username = myuser
jdbc.password = mypassword
hibernate.dialect = org.hibernate.dialect.MySQLDialect
hibernate.show_sql = true
hibernate.format_sql = true

Step 8. Create Controller

package com.websystique.springmvc.controller;

import java.util.List;
import java.util.Locale;

import javax.validation.Valid;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.SessionAttributes;

import com.websystique.springmvc.model.User;
import com.websystique.springmvc.model.UserProfile;
import com.websystique.springmvc.service.UserProfileService;
import com.websystique.springmvc.service.UserService;



@Controller
@RequestMapping("/")
@SessionAttributes("roles")
public class AppController {

	@Autowired
	UserService userService;
	
	@Autowired
	UserProfileService userProfileService;
	
	
	@Autowired
	MessageSource messageSource;

	/**
	 * This method will list all existing users.
	 */
	@RequestMapping(value = { "/", "/list" }, method = RequestMethod.GET)
	public String listUsers(ModelMap model) {

		List<User> users = userService.findAllUsers();
		model.addAttribute("users", users);
		return "userslist";
	}

	/**
	 * This method will provide the medium to add a new user.
	 */
	@RequestMapping(value = { "/newuser" }, method = RequestMethod.GET)
	public String newUser(ModelMap model) {
		User user = new User();
		model.addAttribute("user", user);
		model.addAttribute("edit", false);
		return "registration";
	}

	/**
	 * This method will be called on form submission, handling POST request for
	 * saving user in database. It also validates the user input
	 */
	@RequestMapping(value = { "/newuser" }, method = RequestMethod.POST)
	public String saveUser(@Valid User user, BindingResult result,
			ModelMap model) {

		if (result.hasErrors()) {
			return "registration";
		}

		/*
		 * Preferred way to achieve uniqueness of field [sso] should be implementing custom @Unique annotation 
		 * and applying it on field [sso] of Model class [User].
		 * 
		 * Below mentioned peace of code [if block] is to demonstrate that you can fill custom errors outside the 

validation
		 * framework as well while still using internationalized messages.
		 * 
		 */
		if(!userService.isUserSSOUnique(user.getId(), user.getSsoId())){
			FieldError ssoError =new FieldError("user","ssoId",messageSource.getMessage("non.unique.ssoId", new 

String[]{user.getSsoId()}, Locale.getDefault()));
		    result.addError(ssoError);
			return "registration";
		}
		
		userService.saveUser(user);

		model.addAttribute("success", "User " + user.getFirstName() + " "+ user.getLastName() + " registered 

successfully");
		//return "success";
		return "registrationsuccess";
	}


	/**
	 * This method will provide the medium to update an existing user.
	 */
	@RequestMapping(value = { "/edit-user-{ssoId}" }, method = RequestMethod.GET)
	public String editUser(@PathVariable String ssoId, ModelMap model) {
		User user = userService.findBySSO(ssoId);
		model.addAttribute("user", user);
		model.addAttribute("edit", true);
		return "registration";
	}
	
	/**
	 * This method will be called on form submission, handling POST request for
	 * updating user in database. It also validates the user input
	 */
	@RequestMapping(value = { "/edit-user-{ssoId}" }, method = RequestMethod.POST)
	public String updateUser(@Valid User user, BindingResult result,
			ModelMap model, @PathVariable String ssoId) {

		if (result.hasErrors()) {
			return "registration";
		}

		/*//Uncomment below 'if block' if you WANT TO ALLOW UPDATING SSO_ID in UI which is a unique key to a User.
		if(!userService.isUserSSOUnique(user.getId(), user.getSsoId())){
			FieldError ssoError =new FieldError("user","ssoId",messageSource.getMessage("non.unique.ssoId", new 

String[]{user.getSsoId()}, Locale.getDefault()));
		    result.addError(ssoError);
			return "registration";
		}*/

		userService.updateUser(user);

		model.addAttribute("success", "User " + user.getFirstName() + " "+ user.getLastName() + " updated successfully");
		return "registrationsuccess";
	}

	
	/**
	 * This method will delete an user by it's SSOID value.
	 */
	@RequestMapping(value = { "/delete-user-{ssoId}" }, method = RequestMethod.GET)
	public String deleteUser(@PathVariable String ssoId) {
		userService.deleteUserBySSO(ssoId);
		return "redirect:/list";
	}
	

	/**
	 * This method will provide UserProfile list to views
	 */
	@ModelAttribute("roles")
	public List<UserProfile> initializeProfiles() {
		return userProfileService.findAll();
	}

}

Messages are defined in below mentioned messages.properties file

NotEmpty.user.firstName=First name can not be blank.
NotEmpty.user.lastName=Last name can not be blank.
NotEmpty.user.email=Email can not be blank.
NotEmpty.user.password=Password can not be blank.
NotEmpty.user.ssoId=SSO ID can not be blank.
NotEmpty.user.userProfiles=At least one profile must be selected.
non.unique.ssoId=SSO ID {0} already exist. Please fill in different value.

Step 9. Create Converter

This is the heart of this post. It will take care of mapping the individual userProfile id’s to actual UserProfile Entities in database.

package com.websystique.springmvc.converter;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.convert.converter.Converter;
import org.springframework.stereotype.Component;

import com.websystique.springmvc.model.UserProfile;
import com.websystique.springmvc.service.UserProfileService;

/**
 * A converter class used in views to map id's to actual userProfile objects.
 */
@Component
public class RoleToUserProfileConverter implements Converter<Object, UserProfile>{

	@Autowired
	UserProfileService userProfileService;

	/**
	 * Gets UserProfile by Id
	 * @see org.springframework.core.convert.converter.Converter#convert(java.lang.Object)
	 */
	public UserProfile convert(Object element) {
		Integer id = Integer.parseInt((String)element);
		UserProfile profile= userProfileService.findById(id);
		System.out.println("Profile : "+profile);
		return profile;
	}
	
}

Step 10. Create Spring Configuration

package com.websystique.springmvc.configuration;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.ResourceBundleMessageSource;
import org.springframework.format.FormatterRegistry;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.PathMatchConfigurer;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.ViewResolverRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
import org.springframework.web.servlet.view.JstlView;

import com.websystique.springmvc.converter.RoleToUserProfileConverter;


@Configuration
@EnableWebMvc
@ComponentScan(basePackages = "com.websystique.springmvc")
public class AppConfig extends WebMvcConfigurerAdapter{
	
	
	@Autowired
	RoleToUserProfileConverter roleToUserProfileConverter;
	

	/**
     * Configure ViewResolvers to deliver preferred views.
     */
	@Override
	public void configureViewResolvers(ViewResolverRegistry registry) {

		InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
		viewResolver.setViewClass(JstlView.class);
		viewResolver.setPrefix("/WEB-INF/views/");
		viewResolver.setSuffix(".jsp");
		registry.viewResolver(viewResolver);
	}
	
	/**
     * Configure ResourceHandlers to serve static resources like CSS/ Javascript etc...
     */
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/static/**").addResourceLocations("/static/");
    }
    
    /**
     * Configure Converter to be used.
     * In our example, we need a converter to convert string values[Roles] to UserProfiles in newUser.jsp
     */
    @Override
    public void addFormatters(FormatterRegistry registry) {
        registry.addConverter(roleToUserProfileConverter);
    }
	

    /**
     * Configure MessageSource to lookup any validation/error message in internationalized property files
     */
    @Bean
	public MessageSource messageSource() {
	    ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
	    messageSource.setBasename("messages");
	    return messageSource;
	}
    
    /**Optional. It's only required when handling '.' in @PathVariables which otherwise ignore everything after last '.' in 

@PathVaidables argument.
     * It's a known bug in Spring [https://jira.spring.io/browse/SPR-6164], still present in Spring 4.1.7.
     * This is a workaround for this issue.
     */
    @Override
    public void configurePathMatch(PathMatchConfigurer matcher) {
        matcher.setUseRegisteredSuffixPatternMatch(true);
    }
}

First interesting thing is registration converter we created in previous step with Spring configuration using addFormatters. Next is the method configurePathMatch which provides a workaround (although other workaround exists) for a known bug in spring, which is still found in Spring 4.1.7.RELEASE.

Above Converter setup in XML configuration will be:

	<mvc:annotation-driven conversion-service="conversionService"/>

	<bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
	
		<property name="converters">
			<list>
				<bean id="roleToUserProfile" class="com.websystique.springmvc.converter.RoleToUserProfileConverter" />
			</list>
		</property>
	</bean>

Add initializer class:

package com.websystique.springmvc.configuration;

import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;

public class AppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {

	@Override
	protected Class<?>[] getRootConfigClasses() {
		return new Class[] { AppConfig.class };
	}
 
	@Override
	protected Class<?>[] getServletConfigClasses() {
		return null;
	}
 
	@Override
	protected String[] getServletMappings() {
		return new String[] { "/" };
	}

}

Step 11: Add Views/JSP’s

Note that we are using Bootstrap for styling in JSP.

userslist.jsp

<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>

<head>
	<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
	<title>Users List</title>
	<link href="<c:url value='/static/css/bootstrap.css' />" rel="stylesheet"></link>
	<link href="<c:url value='/static/css/app.css' />" rel="stylesheet"></link>
</head>

<body>
	<div class="generic-container">
		<div class="panel panel-default">
			  <!-- Default panel contents -->
		  	<div class="panel-heading"><span class="lead">List of Users </span></div>
			<table class="table table-hover">
	    		<thead>
		      		<tr>
				        <th>Firstname</th>
				        <th>Lastname</th>
				        <th>Email</th>
				        <th>SSO ID</th>
				        <th width="100"></th>
				        <th width="100"></th>
					</tr>
		    	</thead>
	    		<tbody>
				<c:forEach items="${users}" var="user">
					<tr>
						<td>${user.firstName}</td>
						<td>${user.lastName}</td>
						<td>${user.email}</td>
						<td>${user.ssoId}</td>
						<td><a href="<c:url value='/edit-user-${user.ssoId}' />" class="btn btn-success 

custom-width">edit</a></td>
						<td><a href="<c:url value='/delete-user-${user.ssoId}' />" class="btn btn-danger 

custom-width">delete</a></td>
					</tr>
				</c:forEach>
	    		</tbody>
	    	</table>
		</div>
	 	<div class="well">
	 		<a href="<c:url value='/newuser' />">Add New User</a>
	 	</div>
   	</div>
</body>
</html>

registration.jsp

<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

<html>

<head>
	<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
	<title>User Registration Form</title>
	<link href="<c:url value='/static/css/bootstrap.css' />" rel="stylesheet"></link>
	<link href="<c:url value='/static/css/app.css' />" rel="stylesheet"></link>
</head>

<body>

 	<div class="generic-container">
	<div class="well lead">User Registration Form</div>
 	<form:form method="POST" modelAttribute="user" class="form-horizontal">
		<form:input type="hidden" path="id" id="id"/>
		
		<div class="row">
			<div class="form-group col-md-12">
				<label class="col-md-3 control-lable" for="firstName">First Name</label>
				<div class="col-md-7">
					<form:input type="text" path="firstName" id="firstName" class="form-control input-sm"/>
					<div class="has-error">
						<form:errors path="firstName" class="help-inline"/>
					</div>
				</div>
			</div>
		</div>

		<div class="row">
			<div class="form-group col-md-12">
				<label class="col-md-3 control-lable" for="lastName">Last Name</label>
				<div class="col-md-7">
					<form:input type="text" path="lastName" id="lastName" class="form-control input-sm" />
					<div class="has-error">
						<form:errors path="lastName" class="help-inline"/>
					</div>
				</div>
			</div>
		</div>

		<div class="row">
			<div class="form-group col-md-12">
				<label class="col-md-3 control-lable" for="ssoId">SSO ID</label>
				<div class="col-md-7">
					<c:choose>
						<c:when test="${edit}">
							<form:input type="text" path="ssoId" id="ssoId" class="form-control 

input-sm" disabled="true"/>
						</c:when>
						<c:otherwise>
							<form:input type="text" path="ssoId" id="ssoId" class="form-control 

input-sm" />
							<div class="has-error">
								<form:errors path="ssoId" class="help-inline"/>
							</div>
						</c:otherwise>
					</c:choose>
				</div>
			</div>
		</div>

		<div class="row">
			<div class="form-group col-md-12">
				<label class="col-md-3 control-lable" for="password">Password</label>
				<div class="col-md-7">
					<form:input type="password" path="password" id="password" class="form-control input-sm" 

/>
					<div class="has-error">
						<form:errors path="password" class="help-inline"/>
					</div>
				</div>
			</div>
		</div>

		<div class="row">
			<div class="form-group col-md-12">
				<label class="col-md-3 control-lable" for="email">Email</label>
				<div class="col-md-7">
					<form:input type="text" path="email" id="email" class="form-control input-sm" />
					<div class="has-error">
						<form:errors path="email" class="help-inline"/>
					</div>
				</div>
			</div>
		</div>

		<div class="row">
			<div class="form-group col-md-12">
				<label class="col-md-3 control-lable" for="userProfiles">Roles</label>
				<div class="col-md-7">
					<form:select path="userProfiles" items="${roles}" multiple="true" itemValue="id" 

itemLabel="type" class="form-control input-sm" />
					<div class="has-error">
						<form:errors path="userProfiles" class="help-inline"/>
					</div>
				</div>
			</div>
		</div>

		<div class="row">
			<div class="form-actions floatRight">
				<c:choose>
					<c:when test="${edit}">
						<input type="submit" value="Update" class="btn btn-primary btn-sm"/> or <a 

href="<c:url value='/list' />">Cancel</a>
					</c:when>
					<c:otherwise>
						<input type="submit" value="Register" class="btn btn-primary btn-sm"/> or <a 

href="<c:url value='/list' />">Cancel</a>
					</c:otherwise>
				</c:choose>
			</div>
		</div>
	</form:form>
	</div>
</body>
</html>

registrationsuccess.jsp

<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>


<html>
<head>
	<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
	<title>Registration Confirmation Page</title>
	<link href="<c:url value='/static/css/bootstrap.css' />" rel="stylesheet"></link>
	<link href="<c:url value='/static/css/app.css' />" rel="stylesheet"></link>
</head>
<body>
<div class="generic-container">
	<div class="alert alert-success lead">
    	${success}
	</div>
	
	<span class="well floatRight">
		Go to <a href="<c:url value='/list' />">Users List</a>
	</span>
</div>
</body>

</html>

And a tiny custom stylesheet file:

app.css

body, #mainWrapper {
	height: 100%;
	background-color:rgb(245, 245, 245);
}

body, .form-control{
	font-size:12px!important;
}

.floatRight{
	float:right;
	margin-right: 18px;
}

.has-error{
	color:red;
}

.generic-container {
  position:fixed;
  width:80%;
  margin-left: 20px;
  margin-top: 20px;
  margin-bottom: 20px;
  padding: 20px;
  background-color: #EAE7E7;
  border: 1px solid #ddd;
  border-radius: 4px;
  box-shadow: 0 0 30px black;
}

.custom-width {
    width: 80px !important;
}

Step 12: Build, deploy and Run Application

Now build the war (either by eclipse as was mentioned in previous tutorials) or via maven command line( mvn clean install). Deploy the war to a Servlet 3.0 container . Since here i am using Tomcat, i will simply put this war file into tomcat webapps folder and click on start.bat inside tomcat/bin directory.

Open browser and browse at http://localhost:8080/SpringMVCHibernateManyToManyCRUDExample/

SpringMVCHibernateManyToManyCRUDExample_img1

Click on ‘Add New User’

SpringMVCHibernateManyToManyCRUDExample_img2_1

Submit without filling anything.

SpringMVCHibernateManyToManyCRUDExample_img2_2

Fill in details

SpringMVCHibernateManyToManyCRUDExample_img3

Submit.

SpringMVCHibernateManyToManyCRUDExample_img4

Click on ‘Users List’ link.

SpringMVCHibernateManyToManyCRUDExample_img5

Check the database at this moment.

SpringMVCHibernateManyToManyCRUDExample_img6

SpringMVCHibernateManyToManyCRUDExample_img7

Add more users.

SpringMVCHibernateManyToManyCRUDExample_img8

Click Edit button for User Kenny. Change Roles.

SpringMVCHibernateManyToManyCRUDExample_img9
Submit.

SpringMVCHibernateManyToManyCRUDExample_img10

Verify the database.

SpringMVCHibernateManyToManyCRUDExample_img11

SpringMVCHibernateManyToManyCRUDExample_img12

Now go back to list and click on DELETE for user kenny. It should be history.

SpringMVCHibernateManyToManyCRUDExample_img13

Finally check the database at this moment :

SpringMVCHibernateManyToManyCRUDExample_img14

SpringMVCHibernateManyToManyCRUDExample_img15

SpringMVCHibernateManyToManyCRUDExample_img16
That’s it.

Download Source Code



References

If you like tutorials on this site, why not take a step further and connect me on Facebook , Google Plus & Twitter as well? I would love to hear your thoughts on these articles, it will help me improve further our learning process.

If you appreciate the effort I have put in this learning site, help me improve the visibility of this site towards global audience by sharing and linking this site from within and beyond your network. You & your friends can always link my site from your site on www.websystique.com, and share the learning.

After all, we are here to learn together, aren’t we?

  • Babacar Mame Mbaye Dieng

    Please I need your help Websystique
    Hi my english is so bad, but i will try.
    I have a matter with the conversion in AppConfig. i add a other class and inject the service .In addFormatters method
    but only one conversion works.
    I create 2 forms .

    public void addFormatters(FormatterRegistry registry) {

    registry.addConverter(roleToUserProfileConverter);
    registry.addConverter(contactToUserConverter);
    }

  • metalhead

    Hey,
    Nice tutorial. I have a question: Where should I put the records insertion code in this application, if I were to populate the User and User_Profile tables via code. I mean, in order for the converter to convert the string [] values to UserProfiles there has to be the ‘ADMIN’, ‘USER’ and ‘DBA’ existing in the database and I want to be able to insert those records through code.

    Right now, what I have done is I have put the insert records code in my AppController.java (in newUser GET method). What’s happening now is I am able to successfully insert the records into the database by doing so; but, the registration.jsp is NOT getting populated with the UserProfile values in the respective select box. However, if I run the same application for the second time then it’s getting populated successfully(I’m assuming that the registry.addConverter is not able to fetch the records for the first time since it’s getting called before the AppController.java).

    So, how am I supposed to resolve this issue, if I were to insert initial records into the database through code. Thanks.

  • Sumit Samaddar

    HI Admin,

    Can you explain me how can I add another form in this tutorial to add,edit UserProfile. Because I am trying to implement similar things for Conversion when I am setting it I am getting 400 error. with massage as following —

    WARNING: Failed to bind request element: org.springframework.beans.TypeMismatchException: Failed to convert value of type [org.qz.model.Category] to required type [org.qz.model.Category]; nested exception is org.springframework.core.convert.ConversionFailedException: Failed to convert from type [org.qz.model.Category] to type [org.qz.model.Category] for value ‘Category [id=null, category=null, status=null]‘; nested exception is java.lang.ClassCastException: org.qz.model.Category cannot be cast to java.lang.String

    Please help, it will help me a lot.

    • websystique

      Hi Sumit, Did you configure RoleToUserProfileConverter as shown in the post? From the nested exception, it seems it is not.

      • Sumit Samaddar

        HI,

        It’s done, if I configure it globally for this application it is creating problem so I am attaching with controller using @initbinder. It is working perfectly now. Thanks for replying me, and a good example for newbies like me.

        Thanks again… Keep going.

        • Babacar Mame Mbaye Dieng

          Hi help me i have the same matter

  • Michael Njoroge

    hi.. thanks for the tutorial.. its working ok with tomcat7.. initially, i had a hibernate error which I resolved by changing the hibernate version as 5.2.2.Final

  • http://evgmoskalenko.com/ Евгений

    Hi, can you tell me please, how init pagination for lists?

    Thanks..

    • websystique

      Hi, For pagination means you want to show only x records per page. You can use pagination library [Display Tag e.g.] and send the request to server, asking N recored between X to Y index That means in server you would write a new query method which fetches order-by data and return only N rows.It also means you would sent a request to server each time you change the page. You could also do it in-memory, sending one request, gettting all ordered data in response, and then parsing that response in-memory returning N records on each page change. Hope it helps.

  • Rejean Borgonia

    hello sir.

    how do i set this project up to connect to SQL Server 2008? I changed the application properties with the proper values and installed the jtds driver but i am getting this error

    SEVERE: Servlet.service() for servlet [dispatcher] in context with path [/CompliancePortal] threw exception [Request processing failed; nested exception is org.springframework.transaction.CannotCreateTransactionException: Could not open Hibernate Session for transaction; nested exception is org.hibernate.exception.GenericJDBCException: Could not open connection] with root cause

    java.sql.SQLException: Login failed for user ‘myusername’.

    at net.sourceforge.jtds.jdbc.SQLDiagnostic.addDiagnostic(SQLDiagnostic.java:372)

    at net.sourceforge.jtds.jdbc.TdsCore.tdsErrorToken(TdsCore.java:2988)

    at net.sourceforge.jtds.jdbc.TdsCore.nextToken(TdsCore.java:2421)

    at net.sourceforge.jtds.jdbc.TdsCore.login(TdsCore.java:632)

    at net.sourceforge.jtds.jdbc.JtdsConnection.(JtdsConnection.java:371)

    at net.sourceforge.jtds.jdbc.Driver.connect(Driver.java:184)

    at java.sql.DriverManager.getConnection(DriverManager.java:664)

    at java.sql.DriverManager.getConnection(DriverManager.java:208)

    at org.springframework.jdbc.datasource.DriverManagerDataSource.getConnectionFromDriverManager(DriverManagerDataSource.java:153)

    at org.springframework.jdbc.datasource.DriverManagerDataSource.getConnectionFromDriver(DriverManagerDataSource.java:144)

    at org.springframework.jdbc.datasource.AbstractDriverBasedDataSource.getConnectionFromDriver(AbstractDriverBasedDataSource.java:155)

    at org.springframework.jdbc.datasource.AbstractDriverBasedDataSource.getConnection(AbstractDriverBasedDataSource.java:120)

    at org.hibernate.engine.jdbc.connections.internal.DatasourceConnectionProviderImpl.getConnection(DatasourceConnectionProviderImpl.java:139)

    at org.hibernate.internal.AbstractSessionImpl$NonContextualJdbcConnectionAccess.obtainConnection(AbstractSessionImpl.java:380)

    at org.hibernate.engine.jdbc.internal.LogicalConnectionImpl.obtainConnection(LogicalConnectionImpl.java:228)

    at org.hibernate.engine.jdbc.internal.LogicalConnectionImpl.getConnection(LogicalConnectionImpl.java:171)

    at org.hibernate.internal.SessionImpl.connection(SessionImpl.java:450)

    at org.springframework.orm.hibernate4.HibernateTransactionManager.doBegin(HibernateTransactionManager.java:450)

    at org.springframework.transaction.support.AbstractPlatformTransactionManager.getTransaction(AbstractPlatformTransactionManager.java:373)

    at org.springframework.transaction.interceptor.TransactionAspectSupport.createTransactionIfNecessary(TransactionAspectSupport.java:463)

    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:276)

    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)

    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)

    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207)

    at com.sun.proxy.$Proxy39.findAll(Unknown Source)

    at com.websystique.springmvc.controller.AppController.initializeProfiles(AppController.java:151)

    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)

    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)

    at java.lang.reflect.Method.invoke(Method.java:498)

    at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:221)

    at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:137)

    at org.springframework.web.method.annotation.ModelFactory.invokeModelAttributeMethods(ModelFactory.java:136)

    at org.springframework.web.method.annotation.ModelFactory.initModel(ModelFactory.java:109)

    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:753)

    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:705)

    at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)

    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:959)

    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:893)

    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:967)

    at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:858)

    at javax.servlet.http.HttpServlet.service(HttpServlet.java:622)

    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:843)

    at javax.servlet.http.HttpServlet.service(HttpServlet.java:729)

    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:292)

    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)

    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)

    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240)

    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)

    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:212)

    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106)

    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502)

    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:141)

    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)

    at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:616)

    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88)

    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:528)

    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1099)

    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:670)

    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1520)

    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1476)

    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)

    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)

    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)

    at java.lang.Thread.run(Thread.java:745)

    • websystique

      It seems that your DB credentials or URL is not configured properly.

  • https://sourcedexter.com/ Akshay Pai

    Hi ,

    This is an awesome detailed post on Spring MVC. When I was learning this I was simultaneously working on building an application. In that process, I found issues while handling DB tables without Primary key i Hibernate. Tables that form mapping tables between other entities do not need a primary key and I did not know how to use them. However, I did find the right way to do it, and write a small tutorial on it specifically for this issue. https://sourcedexter.com/2015/09/26/handling-database-tables-with-no-primary-key-in-spring-mvc-and-hibernate/

  • Pingback: Spring Security 4 Hibernate Integration Annotation+XML Example - WebSystique()

  • Jason Dluro

    Creative writing - Coincidentally , if anyone has been looking for a a form , my friend found a blank document here http://goo.gl/kYAZ1O

  • Andrey Gaverdovsky

    Hi, websystiqueadmin. Help me please. How configure UTF-8 encoding in this project.

    • websystique

      Hi Andrey, You can specify it in pom.xml, like:

      UTF-8

  • Pingback: Spring 4 MVC+JPA2+Hibernate Many-to-many-Example - WebSystique()

  • Егор

    please help.. what are better way to add uniqueness to e-mail adress in this example
    without problem with transaction and correct validation…

    • websystique

      Hi Erop, Adding Uniqueness would involve checking against database. At the end Email is just a string [in email format]. You can map it to a unique column [@Column(unique = true)] , and on getting the value from front-end, fire an extra query to check if it exist [like done in isUserSSOUnique], and throw a validation error if it exist.

      • Егор

        Hi!, thank you for answer, but i still do not understand…userService.isUserSSOUnique and userService.saveUser(user) are in different transactions so somebody can come between..
        and violations of the uniqueness of the message will be displayed not with all and only after BindingResult result has no errors..I need to all errors to be displayed at once rather than one by one…

        • websystique

          Hi Erop, I understood what you meant. For that, you may include the logic for uniqueness check as a precondition , right in saveUser. That will preserve consistency.

          • Егор

            Hi, Thanks for your help!

  • Batbold Boldbayar

    If you are getting unknown errors check your ja
    r versions

  • MAndar Teli

    Hi , I am getting below exception

    ARNING: Failed to read HTTP message: org.springframework.http.converter.HttpMessageNotReadableException: Could not read document: Can not deserialize instance of java.util.ArrayList out of START_OBJECT token

    at [Source: java.io.PushbackInputStream@17beb9; line: 1, column: 1]; nested exception is com.fasterxml.jackson.databind.JsonMappingException: Can not deserialize instance of java.util.ArrayList out of START_OBJECT token

    at [Source: java.io.PushbackInputStream@17beb9; line: 1, column: 1]

    Jun 04, 2016 12:19:13 PM org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver logException

    WARNING: Handler execution resulted in exception: Could not read document: Can not deserialize instance of java.util.ArrayList out of START_OBJECT token

    at [Source: java.io.PushbackInputStream@17beb9; line: 1, column: 1]; nested exception is com.fasterxml.jackson.databind.JsonMappingException: Can not deserialize instance of java.util.ArrayList out of START_OBJECT token

    at [Source: java.io.PushbackInputStream@17beb9; line: 1, column: 1]

    Bean class

    @Entity

    @Table(name=”travellerlist”)

    public class Traveller {

    public Traveller(){}

    public Traveller( Long id,

    String userName,

    String destination){

    this.id=id;

    this.userName=userName;

    this.destination=destination;

    }

    @JsonProperty(“id”)

    private Long id;

    private String userName;

    private String destination;

    Controller part

    @RequestMapping(value=”/register/”, method=RequestMethod.POST)

    public ResponseEntity registerTravelBookTraveller(@RequestBody List travellers1 , UriComponentsBuilder ucBuilder)

    {

    try

    {Traveller traveller=(Traveller)travellers1.get(0);

    System.out.println(“inside controller XXXX “+traveller.getDestination());

    travelBookDao.saveOrUpdate(traveller);

    HttpHeaders headers = new HttpHeaders();

    headers.setLocation(ucBuilder.path(“/register/{id}”).buildAndExpand(traveller.getId()).toUri());

    return new ResponseEntity(headers,HttpStatus.CREATED);

    }

    servic e.js

    saveTravellerTrips:function(traveller){

    console.log(‘Test1′+JSON.stringify(traveller));

    return $http.post(‘http://pinkeey:8181/travelbookSpringHibernetAngularJS/register/’,traveller)

    .then(

    function(response){

    console.error(‘after retruning from controller’+response.data);

    return response.data;

    },

    function(errResponse){

    console.error(‘Error while register users2′);

    return $q.reject(errResponse);

    }

    );

    }

    controller.js

    travel.saveTrips=function(){

    //travel.traveller.id=1234577

    travel.travellers1=[travel.traveller];

    console.log(“travellers1″+JSON.stringify(travel.travellers1[0]));

    travel.traveller.id=travelService.saveTravellerTrips(travel.traveller);

    //console.log(“travellers2″+travel.traveller.id);

    travel.getallTravellers();

    };

    What is wrong with this I am stuck

  • MAndar Teli

    Hi I got it your are using converter to loas SessionFactory then why not just Session factory in config

  • MAndar Teli

    Hi Websystique, I have one doubt I dont find HibernateCOnfiguration.java configure in app config can u please explain how it has been getting load

    • websystique

      Hi mandar, HibernateConfiguration is annotated with @Configuration and will be registered as a Configuration class with Spring which may provide @Bean methods. In this configuration class we are creating SessionFactory :

      @Bean
      public LocalSessionFactoryBean sessionFactory(){

      }

      This SessionFactory gets injected in AbstractDao sessionFactory, from where it is accessible in all subclassed daos.

      public abstract class AbstractDao {
      …..
      @Autowired
      private SessionFactory sessionFactory;
      …….
      }

      Please note that SessionFactory has nothing to do with Converter.

  • Pingback: Spring MVC 4 + Spring Security 4 + Hibernate Example - WebSystique()

  • Anirudh Lou

    Your post is very nice sir, however as i downloaded your source code for ”
    Spring 4 MVC+Hibernate Many-to-many JSP Example with annotation” and try to run it on my PC i got this error:

    org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘appConfig’: Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: com.websystique.springmvc.converter.RoleToUserProfileConverter com.websystique.springmvc.configuration.AppConfig.roleToUserProfileConverter; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘roleToUserProfileConverter’: Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: com.websystique.springmvc.service.UserProfileService com.websystique.springmvc.converter.RoleToUserProfileConverter.userProfileService; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘userProfileService’: Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: com.websystique.springmvc.dao.UserProfileDao com.websystique.springmvc.service.UserProfileServiceImpl.dao; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘userProfileDao’: Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private org.hibernate.SessionFactory com.websystique.springmvc.dao.AbstractDao.sessionFactory; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘sessionFactory’ defined in class path resource [com/websystique/springmvc/configuration/HibernateConfiguration.class]: Instantiation of bean failed; nested exception is org.springframework.beans.factory.BeanDefinitionStoreException: Factory method [public org.springframework.orm.hibernate4.LocalSessionFactoryBean com.websystique.springmvc.configuration.HibernateConfiguration.sessionFactory()] threw exception; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘dataSource’ defined in class path resource [com/websystique/springmvc/configuration/HibernateConfiguration.class]: Instantiation of bean failed; nested exception is org.springframework.beans.factory.BeanDefinitionStoreException: Factory method [public javax.sql.DataSource com.websystique.springmvc.configuration.HibernateConfiguration.dataSource()] threw exception; nested exception is java.lang.IllegalStateException: Could not load JDBC driver class [com.mysql.jdbc.Driver]

    How can i resolve the error? By the way i used NetBeans 8.0.2 and I did not use Maven.

    • websystique

      Hi Anirudh, the traces you shared shows the problem. “Could not load JDBC driver class”. You need to check in your [build] system and provide the driver in class path.

  • Amrut Parab

    After adding conversionService to mvc-annotation I am getting below error. How to resolve it?

    org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘conversionService’ defined in ServletContext resource [/WEB-INF/spring/spring-mvc.xml]: Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: Unable to the determine sourceType and targetType which your Converter converts between; declare these generic types.

  • Jeevan K prakash

    Im using XML for configuration.im getting below error while i run the application.
    Please help.

    Apr 29, 2016 9:10:43 AM org.apache.catalina.core.StandardWrapperValve invoke

    SEVERE: Servlet.service() for servlet [appServlet] in context with path [/userList] threw exception [Request processing failed; nested exception is java.lang.NullPointerException] with root cause

    java.lang.NullPointerException

    at com.lean.service.UserProfileServiceImpl.findAll(UserProfileServiceImpl.java:28)

  • Pingback: Spring 4 MVC+Hibernate 4+MySQL+Maven integration + Testing example using annotations - WebSystique()

  • Pingback: Spring 4 MVC+Hibernate 4+MySQL+Maven integration example using annotations - WebSystique()

  • Xyz Amos

    how can we generate models with annotations automatically through reverse engineering ? Now that the project doesn’t has hibernate facets,hibernate reverse engineering doesn’t work anymore.
    thx

  • hzms

    if im changing the version of spring framework, is it affects my project to deploy it? or not?

    • websystique

      Hi,
      It affects your deployable [war file] but does not change the deployment process itself. It is thus possible that while upgrading to a new version of a library, certain dependencies might conflict.

  • Rudradip Misra

    I am getting this exception .Please Help .

    java.lang.IllegalStateException: ContainerBase.addChild: start: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Catalina].StandardHost[localhost].StandardContext[/SpringMVCHibernateManyToManyCRUDExample]]

    ….

    Caused by: java.lang.IllegalArgumentException: Failed to register servlet with name ‘dispatcher’.Check if there is another servlet registered under the same name.

  • Jose Vaca Fernandez

    does The xml configuration go on my web.xml file?

    • websystique

      Hi Jose, This is annotation based configuration, no xml is required.

  • Prateek Ashtikar

    Great example. It would be cool you make this program with JPA. I mean Spring MVC + Security + JPA.

  • seth maragan

    i downloaded the project, it builds succesfully, and is deployed to tomcat 8.0 succesfully. but i keep getting database-related errors when i type in the address – http://localhost:8080/SpringMVCHibernateManyToManyCRUDExample/. I get errors like –

    Request processing failed; nested exception is
    org.springframework.transaction.CannotCreateTransactionException: Could
    not open Hibernate Session for transaction; nested exception is
    org.hibernate.exception.GenericJDBCException: Could not open connection

    how to fix this? i dont know if my database is setup correctly, the tutorial you provided doesnt work, help

    • Xyz Amos

      1.is ur database’s name the same as websystique?
      2.is ur database’s user name and user password the same as “username = myuser password = mypassword”?
      3.or u can customize them in the file named application.properties

  • jaison steephen

    Thank you very much for the clarification that you provided for my previous question. I have one more doubt. I know how control is reaching to —>”@RequestMapping(value = { “/newuser” }, method = RequestMethod.GET)” …….. But I am not understanding how control is reaching to —->”@RequestMapping(value = { “/newuser” }, method = RequestMethod.POST)” by submitting the form—-> “”. How you connect them?

    • websystique

      You get the Registration form using HTTP GET, for URL /newuser. In JSP, you are submitting the form with method ‘post’, and since you are not specifying explicitly any action URL, the existing URL will be used to send the request to, but with POST this time.

      • jaison steephen

        Excellent. Thanks again for the quick reply

  • jaison steephen

    Hi, I am new to spring. I am able to execute this application. Everything working fine. But could you please give me some detail on how this converter is working…I understood that you registered the converter via addFormatters. But I dont understand how the control is reaching to converter, while I click on register button.

    • websystique

      Hi Steephan, We get register view via AppController newUser method, where we provide a user instance as a model attribute. User contains a list of userProfile. Additionally, in AppController, we populate a sessionAttribute roles which will be used to show the list of userprofiles in registration page. We register a converter in AppConfig, capable of converting a String to UserProfile Object.

      When you click on register, Spring will try to populate the model object [User] with user input’s, populating the properties referred using ‘path’ attribute. Since within jsp, we just have String[itemValue='id'], spring will try to convert the selected ids[ list of strings] to userProfiles [referred via 'path']. Since we have registered a custom converter, spring will be able to convert id to user profile[& eventually populate User.userProfiles. Hope it is clear now.

      • jaison steephen

        Sorry for my delay in response. I was trying to understand the application. I have one more doubt…. I know how control is reaching to —>”@RequestMapping(value = { “/newuser” }, method = RequestMethod.GET)” …….. But I am not understanding how control is reaching to —->”@RequestMapping(value = { “/newuser” }, method = RequestMethod.POST)” by submitting the form—-> “”. How you connect them?

  • swapneel

    Very nice tutorial for beginer.

    I am new to spring.I downloaded the source code and imported as maven
    project.I did changes for database username and password.When i ran the
    project using maven, i am getting

    HTTP Status 404 – /SpringMVCHibernateManyToManyCRUDExample/

    I tried your simple Hello World example.But it is also getting the same error.

    • websystique

      Hi Swapneel,

      Perhaps your local tomcat setup with Eclipse is not correct. Please have a look at Setup Tomcat With Eclipse for the same. It should be fine then.

      • swapneel

        Great. Its working now.I did wrong tomcat configuration.Thank you very much.

      • swapneel

        thank you very much.

      • Siham

        Hi! for my case tomcat is set up correctly but when i try to deploy the application i ‘m getting the same error :
        HTTP Status 404 – /SpringMVCHibernateManyToManyCRUDExample/
        can you help plzz?

        • websystique

          Hi Siham, the 404 means’Resource not found’. Are you sure your tomcat setup is fine? I’ve seen a lot of people had this issue and it turned out to be the issue with tomcat setup itself. May i ask you to try following the steps mentioned in the link above and let me know the outcome?

          • Siham

            thank you for replaying but i followed the steps and didn’t work :(

  • Alex

    Hello this post is really helpful. I need some help, hope you can help me please.

    I implemented the example, it works great but a I am trying to make a crud of profiles , when I try to submit a form to save a profile i get an error saying :

    Failed to convert from type com.springmvc.model.UserProfile to type @javax.validation.Valid com.springmvc.model.UserProfile for value ‘UserProfile [id=null, type=NEW PROFILE]‘; nested exception is java.lang.ClassCastException: com.springmvc.model.UserProfile cannot be cast to java.lang.String.

    It only happens when I try to register a new profile to the database. I can insert correctly any other type of entity to the database.

    I hope you can help me, i have been looking the solution with no luck.
    Thanks

    • websystique

      Hi Alex, It seems to be a converter issue. Are you sure your Converter is registered properly, as shown in this post?

      • Alex

        Hello, thank you for your help.

        You are right, There is a Converter issue,when I uncomment the code related to converter the profile is added correctly to the database but now the problem is that I cannot add a user because of the error:

        Failed to convert property value of type java.lang.String to required type java.util.Set for property userProfiles; nested exception is java.lang.IllegalStateException: Cannot convert value of type to required type [com.springmvc.model.UserProfile] for property userProfiles[0]: no matching editors or conversion strategy found

        I ckeked up the code related to the converter and it looks the same as yours.
        Thanks for your help.

        • websystique

          Hi Alex, did you register the converter [in AppConfig] as shown below?

          public void addFormatters(FormatterRegistry registry) {
          registry.addConverter(roleToUserProfileConverter);
          }

          The exception you are mentioning is same as before, you still have the converter issue.

          • Alex

            Hello, yes, in my AppConfig class I have the next code:

            The instance of RoleToUserProfileConverter
            @Autowired
            RoleToUserProfileConverter roleToUserProfileConverter;

            and the converter is also registered

            @Override
            public void addFormatters(FormatterRegistry registry) {
            registry.addConverter(roleToUserProfileConverter);
            }

            and of course, I have created the RoleToUserProfileConverter class which implements Converter and with next content

            @Autowired
            UserProfileService userProfileService;

            public UserProfile convert(Object element) {
            Integer id = Integer.parseInt((String)element);
            UserProfile profile= userProfileService.findById(id);
            return profile;
            }

            But the error still persist. Thanks for your help.

  • indra sam

    please, hi need help

    converters can’t running after save, and always null value. this is a servlet-context.xml

    Kind weird,
    Hope you can help :)

    • indra sam

      please answer my question, I am confused

    • indra sam

      after i trace i found error :
      org.springframework.validation.BeanPropertyBindingResult: 1 errors
      Field error in object ‘user’ on field ‘userProfiles’: rejected value [164]; codes [typeMismatch.user.userProfiles,typeMismatch.userProfiles,typeMismatch.java.util.Set,typeMismatch]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [user.userProfiles,userProfiles]; arguments []; default message [userProfiles]]; default message [Failed to convert property value of type ‘java.lang.String’ to required type ‘java.util.Set’ for property ‘userProfiles’; nested exception is java.lang.IllegalStateException: Cannot convert value of type to required type [id.co.supplier.src.model.userProfiles] for property ‘userProfiles[0]‘: no matching editors or conversion strategy found]

      • websystique

        Hi Indra, Your RoleToUserProfileConverter is not configured. As you are using XML configuration, could you please check that you are configuring the converter properly, like:

        • indra sam

          I have the same configuration of the converter RoleToUserProfileConverter. and the location path in right place. i try to debug and cant found element string on converter.

      • Batbold Boldbayar

        You need to initialize your Converter bean in Application Iinitializer

  • Dmitriu

    Hi, help with a problem!

    • indra sam

      maybe you must check your selection path and items in jsp files.

      • Dmitriu

        I encountered such a problem in my project and decided to test. I created schemas with tables, downloaded the source code, opened in Netbeans and run. Result above.

        • websystique

          Hi Dmitriu,
          Make sure you have database connection. This list is loaded via initializeProfiles method in controller. Addtionally, make sure your RoleToUserProfileConverter is in place.

          • Dmitriu

            RoleToUserProfileConverter is in place. The list ‘roles’ is empty when the table ‘UserProfile’ is empty. Do not load the value of the ‘UserProfileType’.

          • websystique

            You have to populate the USER_PROFILE table, as shown in this blog.

  • Kurniawan

    hi, i use Converter setup in XML configuration on servlet-context.xml , and can’t running, what i need addFormatters and configurePathMatch ?

  • indra sam

    Hi, i am new and learn many to many annotation and not use AbstractDAO, what u have example ?

    • websystique

      Hi Indra,
      This is pure java, so feel free to remove the AbstractDao if you want, putting the necessary logic of AbstractDao in your specific class.

      • indra sam

        OK

  • Diego

    Hey man,
    I’m gettin this error:
    Cannot cast org.springframework.web.SpringServletContainerInitializer to javax.servlet.ServletContainerInitializer

    Kind weird,
    Hope you can help :)

    • Diego

      Oh, i got it:
      Add provided in javax.servlet, and now it’s working :D

  • Diego

    Hello man, I got another trouble:

    Where do i put this code:

    Becasue, the project is not showing the user roles.
    Hope you can help, thanks

    • Diego

      Oh i got it!
      I forgot to put inside :(
      Now it’s working normally :D

      • indra sam

        hi Diego, i use Converter setup in XML configuration on servlet-context.xml like that, and can’t running every save user, what i need addFormatters and configurePathMatch ?

        and my error : org.springframework.validation.BeanPropertyBindingResult: 1 errors

        • Diego

          hello indra,
          post here your .xml config file.

          • Kurniawan

            i have applicationcontext and servlet-context. this is servlet context.

          • indra sam

            hi Diego, i have applicationContext.xml and this is my servlet-context.xml

  • Diego

    Hello, i got another trouble:

  • Diego

    Hello, really liked your project,
    but when i try to type localhost:8080/myproject/newuser, or any request mapping, i get this:

    type Status report
    message /myproject/newuser
    description The requested resource is not available.

    not available, why?

    • websystique

      Hi Diego, It seems your deployment itself is not successful.How exactly are you running this project. Eclipse+Tomcat? If yes, then i would suggest to look at Setup Tomcat+Eclipse. Keep me informed if you remain stuck.

      • Diego

        Hello man,
        You were right, i didn’t depoly the tomcat, now it’s working normally :)
        Thansk man

        • websystique

          Great.

  • Yuck

    Hi, great tutorial but when I build it and try to deploy it on Tomcat 7 I got following error. Any ideas?

    I 31, 2016 5:56:55 ODP. org.apache.catalina.loader.WebappClassLoader validateJarFile

    INFO: validateJarFile(C:UsersPCDesktopsts-bundlepivotal-tc-server-developer-3.1.2.RELEASEtomcat-7.0.64.B.RELEASEwebappsSpringMVCHibernateManyToManyCRUDExampleWEB-INFlibjavax.servlet-api-3.1.0.jar) – jar not loaded. See Servlet Spec 2.3, section 9.7.2. Offending class: javax/servlet/Servlet.class

    I 31, 2016 5:56:56 ODP. org.springframework.web.context.ContextLoader initWebApplicationContext

    INFO: Root WebApplicationContext: initialization started

    I 31, 2016 5:56:56 ODP. org.springframework.web.context.support.AnnotationConfigWebApplicationContext prepareRefresh

    INFO: Refreshing Root WebApplicationContext: startup date [Sun Jan 31 17:56:56 CET 2016]; root of context hierarchy

    I 31, 2016 5:56:56 ODP. org.springframework.web.context.support.AnnotationConfigWebApplicationContext loadBeanDefinitions

    INFO: Registering annotated classes: [class com.websystique.springmvc.configuration.AppConfig]

    I 31, 2016 5:56:57 ODP. org.springframework.web.context.ContextLoader initWebApplicationContext

    SEVERE: Context initialization failed

    java.lang.IllegalStateException: Cannot load configuration class: com.websystique.springmvc.configuration.AppConfig

    at org.springframework.context.annotation.ConfigurationClassPostProcessor.enhanceConfigurationClasses(ConfigurationClassPostProcessor.java:395)

    at org.springframework.context.annotation.ConfigurationClassPostProcessor.postProcessBeanFactory(ConfigurationClassPostProcessor.java:259)

    at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:265)

    at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:126)

    at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:606)

    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:462)

    at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:434)

    at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:306)

    at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:106)

    at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4937)

    at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5434)

    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)

    at org.apache.catalina.manager.ManagerServlet.start(ManagerServlet.java:1258)

    at org.apache.catalina.manager.HTMLManagerServlet.start(HTMLManagerServlet.java:716)

    at org.apache.catalina.manager.HTMLManagerServlet.doPost(HTMLManagerServlet.java:221)

    at javax.servlet.http.HttpServlet.service(HttpServlet.java:647)

    at javax.servlet.http.HttpServlet.service(HttpServlet.java:728)

    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)

    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)

    at org.apache.catalina.filters.CsrfPreventionFilter.doFilter(CsrfPreventionFilter.java:213)

    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)

    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)

    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51)

    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)

    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)

    at org.apache.catalina.filters.SetCharacterEncodingFilter.doFilter(SetCharacterEncodingFilter.java:108)

    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)

    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)

    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222)

    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)

    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:611)

    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171)

    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:100)

    at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:953)

    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)

    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)

    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1041)

    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:603)

    at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:312)

    at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)

    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)

    at java.lang.Thread.run(Unknown Source)

    Caused by: java.lang.OutOfMemoryError: PermGen space

    at java.lang.ClassLoader.defineClass1(Native Method)

    at java.lang.ClassLoader.defineClass(Unknown Source)

    at java.security.SecureClassLoader.defineClass(Unknown Source)

    at org.apache.catalina.loader.WebappClassLoader.findClassInternal(WebappClassLoader.java:2918)

    at org.apache.catalina.loader.WebappClassLoader.findClass(WebappClassLoader.java:1174)

    at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1669)

    at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1547)

    at org.springframework.context.annotation.ConfigurationClassEnhancer.newEnhancer(ConfigurationClassEnhancer.java:112)

    at org.springframework.context.annotation.ConfigurationClassEnhancer.enhance(ConfigurationClassEnhancer.java:100)

    at org.springframework.context.annotation.ConfigurationClassPostProcessor.enhanceConfigurationClasses(ConfigurationClassPostProcessor.java:385)

    at org.springframework.context.annotation.ConfigurationClassPostProcessor.postProcessBeanFactory(ConfigurationClassPostProcessor.java:259)

    at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:265)

    at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:126)

    at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:606)

    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:462)

    at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:434)

    at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:306)

    at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:106)

    at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4937)

    at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5434)

    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)

    at org.apache.catalina.manager.ManagerServlet.start(ManagerServlet.java:1258)

    at org.apache.catalina.manager.HTMLManagerServlet.start(HTMLManagerServlet.java:716)

    at org.apache.catalina.manager.HTMLManagerServlet.doPost(HTMLManagerServlet.java:221)

    at javax.servlet.http.HttpServlet.service(HttpServlet.java:647)

    at javax.servlet.http.HttpServlet.service(HttpServlet.java:728)

    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)

    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)

    at org.apache.catalina.filters.CsrfPreventionFilter.doFilter(CsrfPreventionFilter.java:213)

    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)

    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)

    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51)

    • websystique

      Hi Yuck,
      You are using Tomcat 7.0.X, which supports Servlet 3.0 API ( not 3.1 as shown in dependency section within pom.xml). You can either move to Tomcat 8 ( which uses Servlet 3.1 API), OR change the dependency in POM.xml as 3.0.0 for javax.servlet-api. Additionally, you may specify provided as they are bundled with tomcat. Let me know if you still face any issue.

  • Devarshi Shah

    can i see ur web.xml file?

    • Devarshi Shah

      the code you have posted in not running.

      • websystique

        Hi Devarshi,

        It’s Servlet 3.x app, so you don’t need web.xml. Now, about the code, it is not running in your system probably because your eclipse+tomcat setup is not configured properly. Have a look at Setup Tomcat With Eclipse to configure it properly. Let me know if you still face any issue.

        • Devarshi Shah

          hey my tomcat is working properly. there is some issue with bean in appconfig. if you dont mind can i send you my entire project?

  • Greg H

    Hi, I’m trying to get this example up and running using the maven jetty plugin in eclipse. Unfortunately, I haven’t been able to have any luck getting this up and running because I can’t figure out how to rut it in debug. The example only shows how to build the war. Any hints? I’m assuming this is primarily because there is no web.xml or other files.

    Thanks for your help. Otherwise great example!

    • websystique

      Hi Greg,

      Probably the reason is that your Jetty plugin is not configured properly.

      Here is the Official Plugin Doc. Plugin itself can be found here. Note that Jetty 9.3.X requires Java 8 to work, due to this bug.

      Add following to your pom.xml, plugins section(assuming you use java 1.7):

      org.eclipse.jetty
      jetty-maven-plugin
      9.2.14.v20151106

      10

      /SpringMVCHibernateManyToManyCRUDExample

      This should unblock you. Let me know if you still face any issue.

      • Greg H

        I actually just saw that bug and made the fix right before you commented. Thanks for the help! I’m trying to build upon your example now. When I add a new object trying to make a new many-to-many relationship, I receive the following error:

        org.hibernate.QueryException: could not resolve property: type of: com.websystique.springmvc.model.Institution
        at org.hibernate.persister.entity.AbstractPropertyMapping.propertyException(AbstractPropertyMapping.java:83)
        at org.hibernate.persister.entity.AbstractPropertyMapping.toType(AbstractPropertyMapping.java:77)
        at org.hibernate.persister.entity.AbstractEntityPersister.getSubclassPropertyTableNumber(AbstractEntityPersister.java:1995)
        at org.hibernate.persister.entity.BasicEntityPropertyMapping.toColumns(BasicEntityPropertyMapping.java:61)
        at org.hibernate.persister.entity.AbstractEntityPersister.toColumns(AbstractEntityPersister.java:1970)
        at org.hibernate.loader.criteria.CriteriaQueryTranslator.getColumns(CriteriaQueryTranslator.java:518)
        at org.hibernate.loader.criteria.CriteriaQueryTranslator.getColumnsUsingProjection(CriteriaQueryTranslator.java:482)
        at org.hibernate.criterion.Order.toSqlString(Order.java:126)
        at org.hibernate.loader.criteria.CriteriaQueryTranslator.getOrderBy(CriteriaQueryTranslator.java:431)
        at org.hibernate.loader.criteria.CriteriaJoinWalker.(CriteriaJoinWalker.java:123)
        at org.hibernate.loader.criteria.CriteriaJoinWalker.(CriteriaJoinWalker.java:92)
        at org.hibernate.loader.criteria.CriteriaLoader.(CriteriaLoader.java:97)
        at org.hibernate.internal.SessionImpl.list(SessionImpl.java:1699)
        at org.hibernate.internal.CriteriaImpl.list(CriteriaImpl.java:380)
        at com.websystique.springmvc.dao.InstitutionDaoImpl.findAll(InstitutionDaoImpl.java:29)
        at com.websystique.springmvc.service.InstitutionServiceImpl.findAll(InstitutionServiceImpl.java:29)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:497)
        at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:317)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:190)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)
        at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:99)
        at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:281)
        at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
        at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207)
        at com.sun.proxy.$Proxy56.findAll(Unknown Source)
        at com.websystique.springmvc.controller.AppController.initializeInstitution(AppController.java:155)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:497)
        at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:221)
        at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:137)
        at org.springframework.web.method.annotation.ModelFactory.invokeModelAttributeMethods(ModelFactory.java:136)
        at org.springframework.web.method.annotation.ModelFactory.initModel(ModelFactory.java:109)
        at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:753)
        at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:705)
        at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
        at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:959)
        at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:893)
        at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:967)
        at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:858)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:735)
        at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:843)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:848)
        at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:684)
        at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:503)
        at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:137)
        at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:557)
        at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:231)
        at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1086)
        at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:429)
        at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:193)
        at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1020)
        at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:135)
        at org.eclipse.jetty.server.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:255)
        at org.eclipse.jetty.server.handler.HandlerCollection.handle(HandlerCollection.java:154)
        at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:116)
        at org.eclipse.jetty.server.Server.handle(Server.java:370)
        at org.eclipse.jetty.server.AbstractHttpConnection.handleRequest(AbstractHttpConnection.java:494)
        at org.eclipse.jetty.server.AbstractHttpConnection.headerComplete(AbstractHttpConnection.java:971)
        at org.eclipse.jetty.server.AbstractHttpConnection$RequestHandler.headerComplete(AbstractHttpConnection.java:1033)
        at org.eclipse.jetty.http.HttpParser.parseNext(HttpParser.java:644)
        at org.eclipse.jetty.http.HttpParser.parseAvailable(HttpParser.java:235)
        at org.eclipse.jetty.server.AsyncHttpConnection.handle(AsyncHttpConnection.java:82)
        at org.eclipse.jetty.io.nio.SelectChannelEndPoint.handle(SelectChannelEndPoint.java:696)
        at org.eclipse.jetty.io.nio.SelectChannelEndPoint$1.run(SelectChannelEndPoint.java:53)
        at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:608)
        at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:543)
        at java.lang.Thread.run(Thread.java:745)

        I’m confused because the new object was just cut and paste of the UserProfile object but with a different name. Any idea why this is occurring?

        • websystique

          Hi Greg,

          Do you have a type property defined in your Institution model class, something like shown below?

          @Column(name=”TYPE”, length=15, unique=true, nullable=false)
          private String type = XYZType.USER.getUserProfileType();

          If not, could you please show your com.websystique.springmvc.model.Institution class & InstitutionDaoImpl.findAll() method?

          • Greg H

            I don’t have a type property defined. Here is the institution class:

            @Entity
            @Table(name=”INSTITUTION”)
            public class Institution {
            @Id @GeneratedValue(strategy=GenerationType.IDENTITY)
            private Integer id;

            public void setId(Integer id) {
            this.id = id;
            }

            @Override
            public int hashCode() {
            final int prime = 31;
            int result = 1;
            result = prime * result + ((id == null) ? 0 : id.hashCode());
            return result;
            }

            @Override
            public boolean equals(Object obj) {
            if (this == obj)
            return true;
            if (obj == null)
            return false;
            if (!(obj instanceof Institution))
            return false;
            Institution other = (Institution) obj;
            if (id == null) {
            if (other.id != null)
            return false;
            } else if (!id.equals(other.id))
            return false;
            return true;
            }

            @Override
            public String toString() {
            return “UserProfile [id=" + id + "]“;
            }
            }

            and here is the InstitutionDaoImpl:

            @Repository(“institutionDao”)
            public class InstitutionDaoImpl extends AbstractDaoimplements InstitutionDao{

            public Institution findById(int id) {
            return getByKey(id);
            }

            @SuppressWarnings(“unchecked”)
            public List findAll() {
            Criteria crit = createEntityCriteria();
            crit.addOrder(Order.asc(“type”));
            return (List)crit.list();
            }
            }

          • websystique

            If you only have id property available, then in Dao findAll method, you should be using ‘id’ instead of ‘type’.

          • Greg H

            I apologize, I pasted the wrong bit of code. My edit shows the correct class.

          • Greg H

            Ok, I see what you meant by “type” there in the sort order criteria of the DaoImpl. I changed that to name and things seem to be working now. Thanks again for the help and keep up with the amazin tutorials!

  • Jithin Mathew

    First of all, this is really a great tutorial for beginners like me.Really loved it and build just like what you taught here.

    Just to know, if you have any JUnit testing code for this same project listed above!It would be really great if you could share the same if you have one, so that it will help a lot with beginners like me!

    Thanks in advance!

    • websystique

      Hi Jithin, Take a look at this post. These two posts are almost same, so you will get idea about how to write tests for them. If you get stuck somewhere, don’t hesitate to shout.

  • Pingback: Spring MVC 4 FileUpload-Download Hibernate+MySQL Example - WebSystique()

  • Ahmed Deen

    Role’s values are not passing to controller, can u pls help me

    • websystique

      Hi Ahmed, Did you configure the converter [RoleToUserProfileConverter] as shown in this post? BTW, did you make any changes in project after download, because i did not see this error before?

      • Ahmed Deen

        Thanks Websystique, Its now working fine,

        Actually i configured converter [RoleToUserProfileConverter] package name wrongly.

        Very very thanks for your quick response!

  • Mario Cuollo Conforti

    Hello websystique, your tutorials are great! I’m learning a lot from them. I have a question for you. If I want to list all the users of a certain type (i would like a “USER” list, an “ADMIN” list and so on. I’m trying to modify the userService.findAllUsers(); to pass to it a “type” parameter to use a filter for the query, but with no success. I will pass this “type” via GET and taking it via @RequestParam in the controller.

    But, i don’t know how to use your infrastructure to achieve it.

    I was trying in UserDaoImpl something like this, but with no effect because the table name is not a User parameter…

    public List findAllUsers(int typeId) {

    Criteria criteria = createEntityCriteria();
    criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);

    @SuppressWarnings(“unchecked”)
    List users = (List) criteria.createAlias(“users_user_profile”, “uup”).createAlias(“user_profile”, “up”).add(Restrictions.eq(“up.id”, typeId)).list();

    return users;

    }

    • websystique

      Hi Mario,

      This should unblock you:

      public List findAllUsersOfSpecificType(String type) {

      Criteria criteria = createEntityCriteria().addOrder(Order.asc(“firstName”));
      if(StringUtils.isNotBlank(type)){
      criteria.createAlias(“userProfiles”, “profiles”);//inner join
      criteria.add(Restrictions.eq(“profiles.name”, type.toUpperCase()));
      }

      criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);//To avoid duplicates.
      List users = (List) criteria.list();
      return users;
      }

      Let me know if it does not help you.

      • Mario Cuollo Conforti

        Thanks, it’s perfect!!! The only thing, if you want to publish it, is that “criteria.add(Restrictions.eq(“profiles.name”, type.toUpperCase()));” should be

        “criteria.add(Restrictions.eq(“profiles.type”, type.toUpperCase()));”

        I can reach the list in this way: /users?type=admin or/users?type=user

        Than the controller is

        @RequestMapping(value = “/users”, method=RequestMethod.GET)
        public String listUserByType(ModelMap model, @RequestParam String type){
        List users = userService.findAllUsersOfSpecificType(type);
        model.addAttribute(“users”, users);
        return path+”/users”;

        }

        • websystique

          Glad it was helpful.

  • Stepan Cleverjava

    The more I read the more I understand how good your posts are. Thanks for them. I would like to ask you about this post.

    As far as I understood, in the following chain: public String newUser(…) –> registration.jsp –> public String saveUser(…) you bind twice: 1) An empty user created in the newUser(…) method with registration.jsp (that is why the fields are empty) 2) Nonempty object created in registation.jsp (the fields are mandatory) with the one passing to saveUser(…) method. Correct me if I’m wrong.

    My question is why do you need double binding? Instead you could only exploit binding registration.jsp –> public String saveUser(@ModelAttribute…). In that case instead of e.g. you could use plain

    Thanks in advance for you response!

    • websystique

      Hi Stepan,

      Sorry for late reply. I kept them separate to cleanly apply validation. You can of course handle it as you mentioned but then you may need to put some conditional check to handle validations.Hope it helps.

      • Stepan Cleverjava

        Thanks a lot!
        While waiting for your response I’ve got another question. It looks like that @ModelAttribute and @SessionAttributes play the roles of old request and session attributes. Then a natural question arises – is there some new analogue of context attribute?
        Again thank you for your current and further replies!

        • websystique

          Hi Stepan,

          Not that i am aware about. But you can get the behavior you want by implementing ServletContextAware in your bean class and then eventually using setAttribute and getAttribute on ServletContext. An example can be found here.

  • Aravind Karthick

    I am getting the olllowing error. Kindly help.

    • vamshi

      Hi,

      Try this (from Stackoverflow)

      Another way is to edit the project facet configuration file itself: org.eclipse.wst.common.project.facet.core.xml

      Change the dynamic web module version in this line to 3.1 –

      And then:

      Right-click on the project (in the Project Explorer panel).

      Select Maven » Update Project (or press Alt+F5)

      You’ll find this file in the .settings directory within the Eclipse project.

      • Aravind Karthick

        I tried this one many times (Attached the screen shot already).. But still i’m facing the issue.

        I am using the following tools
        1) Eclipse Mars

        2) JDK 1.7
        3) Tomcat 7.X https://uploads.disquscdn.com/images/e40c5f33dff1f828079676bf6a2aee642151b9475ddd0062650667a29ddc1832.jpg
        4) Maven 3.3
        5) My Sql – Xampp

        I find no means to rectify this issue.

        • websystique

          Hi Aravind, why don’t you simply remove the error (select the top level node named “errors” in Problems window, delete it). It’s Eclipse idiosyncrasy, project itself should work fine. Additionally, you may want to look at Setting tomcat with eclipse in case you are facing any issue with Eclipse setup. Let me know if you have any other issues.

  • http://junjunguo.com/ guojunjun

    Hi websystique,

    how do to make it bidirectional ?

    User knows UserProfile by:

    “`private Set userProfiles = new HashSet();“`

    if I add this to UserProfile side it would bidirectional:

    “`private Set users = new HashSet();“`

    I’v tried “`fetch = FetchType.LAZY, FetchType.EAGER, cascade = {CascadeType.ALL} …“`

    but cannot make it work, any suggestion for this?

    Best greetings

    • websystique

      Hi Guojunjun,

      I would suggest you to first go through Hibernate Many-To-Many-Bidirectional Example post. It should clear your doubts. Do let me know if you still face other issues.

      • http://junjunguo.com/ guojunjun

        Thank you very much for your reply @websystique:disqus, I do checked the example you posted, the database works as it should, but when it comes to request (with servlet, spring implemented) the No Session problem comes again if I use ‘fetch = FetchType.LAZY’, (and I also tried ‘fetch = FetchType.EAGER’ then I have ‘com.fasterxml.jackson.databind.JsonMappingException: Premature EOF (through reference chain’ problem, but I do want to use FetchType.LAZY, this is the one could handle more request, with my understanding)

        How do I fix this?

        Best greetings

        • websystique

          Hi Guojunjun,

          Sorry for late reply. What about creating a separate method in UserProfileDaoImpl where you can initialize the users collection, which you can then use (via service) in AppController, something like ….

          //UserProfileDaoImpl
          public UserProfile findByTypeInitialized(String type) {
          Criteria crit = createEntityCriteria();
          crit.add(Restrictions.eq(“type”, type));
          UserProfile userProfile = (UserProfile) crit.uniqueResult();
          if(userProfile!=null){
          Hibernate.initialize(userProfile.getUsers());
          }
          return userProfile;
          }

          //AppController
          @RequestMapping(value = { “/edit-userprofile-{type}” }, method = RequestMethod.GET)
          public String editUserProfile(@PathVariable String type, ModelMap model) {
          UserProfile userProfile = userProfileService.findByTypeInitialized(type);
          model.addAttribute(“userProfile”, userProfile);
          model.addAttribute(“edit”, true);
          return “userprofileregistration”;
          }

          This way you keep the other setup untouched and still get possibility of avoiding Lazy Init Exception.

          Keep me informed about your progress on this.

          • http://junjunguo.com/ guojunjun

            Hi websystique, thank you very much for your solution, I thought something similar, but of course not as good as yours:)

            I got this error with the solution you suggested:
            `object references an unsaved transient instance – save the transient instance before flushing`

            So I added ‘cascade = {CascadeType.ALL}’ to first make it bidirectional, then use ‘@JsonIgnore’ at child side, to stop the infinite loop problem. After this I added your solution to get it bidirectional again :)

            Thank you very much agin for all your helps :)

            Best greetings

            Junjun Guo

  • Marcos Lozina

    Hello again, gread tutorial, I did not find anything like it in the entire web. You are java certified? one question: where you define “welcome-file” originally defined in the web.xml ??

    • websystique

      Hi Marcos,
      Glad you liked it. For the welcome page, I have defined it in default controller method(‘/’). Look at listUser method in AppController class.

  • http://junjunguo.com/ guojunjun

    Hei websystique, thanks for another great tutorial, I knew I will find a solution from your tutorials and I got it form this one :)

    “org.hibernate.LazyInitializationException – could not initialize proxy – no Session. To avoid it, you need to initialize the collection on demand by callingHibernate.initialize(user.getUserProfiles());”

    Do you know any other solutions than calling Hibernate.initialize(X.X) in all my finding methods ?

    Best greetings :)

    • websystique

      One popular alternative [there might be others as well] is to use OpenSessionInView pattern. Most of the frameworks even provide some sort of implementation for that. Personally, based on my experience, i always prefer to use Hibernate.initialize to keep things separate.

      • http://junjunguo.com/ guojunjun

        Thank you very much for your answer :) I will stay with this solution, and concentrate on gaining more understanding on Spring and Hibernate frameworks :)

        best greetings

  • Marcos Lozina

    Hello again !One question: where is the file where you register the converter? I did not find the XML file in the project

    • websystique

      Hi Marcos, It’s right there in AppConfig, in method addFormatters. This project is totally Annotations based, no XML required.

  • Marcos Lozina

    Gread post, very high quality information. Congratulations, (sorry for my English, I’m Hispanic community java :) I just have two questions. 1) I deploy app in tomcat 8 and it work ! but if i try deploy in the Widfly 8 server, I need configure a JAAS autentication? 2) To run app in the PostgreSQL, i only need edit the aplication.properties, to change the parameter? or need edit the hibernate mapping too?

    • websystique

      Hi Marcos,

      Sorry for being late. I have no experience on widfly you mentioned, there i may not help much. But for PostgreSQL, yes you need to change the dialect in application.properties & may need to adapt the DDL i mentioned at the beginning of post, no mapping change should be required.