Resolving Spring error: No unique bean of type is defined expected single matching bean but found 2


Error for ServeChild1Controller: No unique bean of type [com.service.ParentService] is defined: expected single matching bean but found 2 child1service, child2service

This error occurs if there are two beans implementing the same interface and referenced.

public interface ParentService{}
@Service("child1service")    
public class Child1 implements ParentService{}

@Service("child2service")
public class Child2 implements ParentService{}
public class ServeChild1Controller extends AbstractController{

 @Autowired
 public ServeChild1Controller(@Qualifier("child1service") ParentService child1service){
 super(child1service)
  } 

The following problem can be resolved using @Qualifier

@Service("child1service")
@Qualifier("child1service")
public class Child1 implements ParentService{}

@Service("child2service")
@Qualifier("child2service")
public class Child2 implements ParentService{}
Advertisements

Load property file outside the war file using Spring 3


At times it is required to load properties not present in the war file. Typical usage can be have a war/jar file bundled and having property file for different environment such as dev, QA and PROD. It easy to put outside the war so that everytime build is not required. Fortunately is pretty simple in Spring 3.

Just mention this in spring config

<bean id="placeholderConfigConfig" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="systemPropertiesModeName">
    <value>SYSTEM_PROPERTIES_MODE_OVERRIDE</value>
</property>
<property name="ignoreUnresolvablePlaceholders">
    <value>true</value>
</property>
<bean
    class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
    <property name="location" value="file:${config}" />
</bean>

The value of config can be set a -Dconfig in runtime environment. Like it project is run using maven it can be set as MAVEN_OPTS parameter.

It you want smarter way then

 <context:property-placeholder location="file:${config}"/>

Spring 3 MVC Annotations tutorial


This post will give brief idea about creating views, controller in Spring.

Note: The code can be downloaded. URL for download is present at the end.

A simple example : Store the information of a person. The property of a person is Name and City with a unique id.
The model class will be


public class PersonForm {

	private String name;
	private String city;
	private int id = -1;
	
	public PersonForm(int id,String name, String city ) {
		this.name = name;
		this.city = city;
		this.id = id;
	}
	public PersonForm() {
		// TODO Auto-generated constructor stub
	}
	// include getters and setters
}

Following functionalities can be defined:

  • Create a user
  • Edit a user
  • Delete a user
  • Show all users

The url mappings can be defined

URL Function jsp page
/person , Request Type = GET Show all users show.jsp
/person , Request Type = POST Save a user user.jsp
/person/newuser , Request Type = GET/td>

Show a blank form to enter user details user.jsp
/person/delete/{id} , Request Type = POST Delete a user show.jsp
/person/update/{id} , Request Type = POST Update a user user.jsp

Note: The user is stored simply using a HashMap ( for simplicity) . Ideally all calls should go to DB.
Lets create the Controller where all the actions happen.

@RequestMapping("/person")
@Controller
/** Displaying CRUD functionality. **/
public class PersonController {
	
	Map<Integer, PersonForm> personList = new HashMap<Integer, PersonForm>();
	static int  id = 0;
	
	/**
	 * Save a user and return back to display all users
	 */
	@RequestMapping(method=RequestMethod.POST)
	public ModelAndView save(PersonForm form,BindingResult errors, HttpServletRequest request, HttpServletResponse response){
		if(form.getId() == -1){
		id++;
		form.setId(id);
		personList.put(id,form);
		}else{
			personList.put(form.getId(), form);
		};
		ModelMap map = new ModelMap();
		Iterator iter = personList.keySet().iterator();
		List<PersonForm> newMap = new ArrayList<PersonForm>();
		while(iter.hasNext()){
			Object key = iter.next();
			if(key != null)
				newMap.add(personList.get(key));
		}
		map.put("persons",newMap);
		return new ModelAndView("show",map);
	}
	
	@RequestMapping(value="/newuser",method=RequestMethod.GET)
	public ModelAndView newUser(){
		PersonForm form = new PersonForm();
		ModelMap map = new ModelMap();
		map.put("person", form);
		return new ModelAndView("user",map);
	}
	
	/**
	 * 
	 * Display all users
	 */
	@RequestMapping(method=RequestMethod.GET)
	public String displayAll( HttpServletRequest request){
		ModelMap map = new ModelMap();
		Iterator iter = personList.keySet().iterator();
		List<PersonForm> newMap = new ArrayList<PersonForm>();
		while(iter.hasNext()){
			Object key = iter.next();
			if(key != null)
				newMap.add(personList.get(key));
		}
		map.put("persons",newMap);
		request.setAttribute("persons", newMap);
		return "show";
	}
	/** Delete a user and return back to all list **/
	@RequestMapping(value="/delete/{id}")
	public String delete(@PathVariable String id, HttpServletRequest request){
		personList.remove(Integer.parseInt(id));
		Iterator iter = personList.keySet().iterator();
		List<PersonForm> newMap = new ArrayList<PersonForm>();
		while(iter.hasNext()){
			Object key = iter.next();
			if(key != null)
				newMap.add(personList.get(key));
		}
		request.setAttribute("persons", newMap);
		return "show";
	}
	/** Update a user and return back to all list **/
	@RequestMapping(value="/update/{id}")
	public ModelAndView update(@PathVariable String id){
		ModelMap map = new ModelMap();
		map.put("person", personList.get(Integer.parseInt(id)));
		return new ModelAndView("user",map);
	}
}

Here all the actions happen:

  • @Controller: is used to tell Spring that PersonController is a controller
  • @RequestMapping(class-level): Annotation for mapping web requests onto specific handler classes and/or handler methods.All urls inside this controller should precede with the url mentioned as the value.
  • @RequestMapping(method-level): The function will be called if the url maps the given value. Other attributes can be set as RequestType(GET or POST etc) .
  • ModelAndView: This class merely holds both(Model and view) to make it possible for a controller to return both model and view in a single return value. The object tell which view to resolve and what model object should be passed.
  • ModelMap: Implementation of Map(LinkedHashMap),building model data for use with UI tools.Basically replacement of setting values as request attribute.
  • Method such as delete and displayAll returns the String. The return value is mapped to view name. The view name is resolved using InternalResourceViewResolver configured in mvc-dispatcher-servlet.xml.
  • The update or delete url are mapped as /update/{id}.. Any parameter defined in {} can be accessed using @PathVariable
  • Note: I have defined controller to view mapping in couple of ways. There are more ways to define.

Now its the turn of views:
user.jsp

<%@ taglib uri="http://www.springframework.org/tags/form" prefix="form" %>
<%@ taglib uri="http://www.springframework.org/tags" prefix="spring" %>
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
<form:form commandName="person" method="post" action="/SpringMVC/person">
<form:hidden path="id" id="id" />
<table>
	<tr>
		<td><label>Name</label></td>
		<td><form:input path="name" id="name"/></td>
	</tr>
	<tr>
		<td><label>City</label></td>
		<td><form:input path="city" id="city"/></td>
	</tr>
	<tr>
		<td><input type="submit" name="save" value="save"/></td>
	</tr>
</table>	
</form:form>
</body>
</html>

This view is used to save and update the users.

index.jsp

<%@ page language="java" errorPage="/error.jsp" pageEncoding="UTF-8" contentType="text/html;charset=utf-8" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<html>
<body>
	<h1>List Of People</h1>
	<table>
	<tr>
		<th>Name</th>
		<th>City</th>
	</tr>
	<c:forEach items="${persons}" var="person">
	<tr>
		<td>${person.name}</td>
		<td>${person.city}</td>
		<td>
			<a href="/SpringMVC/person/delete/${person.id}">DELETE</a>
		</td>
		<td>
			<a href="/SpringMVC/person/update/${person.id}">EDIT</a>
		</td>
	</tr>
	</c:forEach>
	</table>	
</body>
</html>

Now the configuration:
The web.xml is pretty basic .. Declaring the org.springframework.web.servlet.DispatcherServlet and loading the spring servlet.xml. The code can be downloaded at the end.

mvn-dispatcher-servlet.xml is very basic for this example

<context:component-scan base-package="com.common.controller" />
	<context:annotation-config />
	<bean
		class="org.springframework.web.servlet.view.InternalResourceViewResolver">
		<property name="prefix">
			<value>/WEB-INF/pages/</value>
		</property>
		<property name="suffix">
			<value>.jsp</value>
		</property>
	</bean>

This <context:annotation-config /> tells that spring in annotation enabled.
This <context:component-scan base-package> tells where beans are configured.
And InternalResourceViewResolver resolve view names to jsp pages present in WEB-INF/pages.

Download Code