Spring and Hibernate with Annotations

A Word about Flow

Since it is sometimes confusing to follow the entire flow of a Spring MVC web application, let’s take a minute and look at the ManageDepartment and EditDepartment flow.  We’ll use the example of an end-user editing an existing department called “Sales”.  The will also erase the name and submit the edit form (an error) so that we can follow the error flow.

  1. User navigates to manageDepartments.html in the browser.
  2. Spring finds the mapping for manageDepartments.html, which it finds at ManageDepartmentsController.handleRequest().
  3. HandleRequest() returns the name of a view to display to the end-user.  The name returned is “manageDepartments”.
  4. Using the ViewResolver, Spring finds the manageDepartments view in /WEB-INF/jsp/manageDepartments.jsp.  The JSP page is rendered and returned to the end-user.
  5. The end-user sees a list of existing departments in the browser.  They find the “Sales” department in the list, and click on the “edit” link next to it.
  6. The edit link calls “editDepartment.html” in the browser, with two parameters: action=edit and id= the id of the Sales department.
  7. Spring looks up the mapping for a GET on editDepartment.html.  It finds the mapping in EditDepartment.showForm(), which is handled by the superclass, MappedModelFormController.showForm().
  8. ShowForm() sees that an ID has been supplied, and pulls the Sales Department from the database.  It pushes the Sales Department into the Model as “mappedModel”, and also the type (Department) as “mappedModelName”.  It returns a view name of “editDepartment”.
  9. Again using the ViewResolver, Spring finds the actual view for name “editDepartment” at /WEB-INF/jsp/editDepartment.jsp.  It renders the JSP and returns the result to the end-user.
  10. The user then edits the fields of the Sales Department.  By accident, they completely erase the name of the Department and then hit the “Save” button.
  11. Any submit button on a Spring form will cause a POST to be performed to the original URL (in this case, “editDepartment.html”).  Spring finds a handler for a POST to editDepartment.html at EditDepartment.handleSubmit(), which is handled by the superclass, MappedModelFormController.handleSubmit().
  12. HandleSubmit() sees that this is a “Save” (because submitType == the value of the button pressed by the end user).  It attempts to validate the newly bound object (that is, the @ModelAttribute passed in), but this fails with an error since the name is now empty.  It pushes the errors from the validtor into the Spring Model, and shows the edit form again, “editDepartment.html”.
  13. Again, Spring finds a mapping for a GET to editDepartment.html at EditDepartment.showForm().  This time, when the editDepartment.jsp page is rendered, the <spf:errors> tags will show the end user that the name is required.
  14. The end-user corrects the mistake, and sets the Department name to “Sales and Marketing”.  The end-user clicks “Save” again.
  15. Just like in step 11, Spring sends the POST to handleSubmit().  This time, the @ModelAttribute will pass validation, and handleSubmit() will save the changed Department to the database via the modelDao.  It will return a redirect to URL “manageDepartments.html”.
  16. Since the name of the requested URL is manageDepartments.html, we go back to step 1 and start it all over again.  This time the list will show the new Department name of “Sales and Marketing”.

Now, let’s look at the Employee side.  Employees are managed identically (well, almost) to Departments.  There is a ManageEmployee controller, EditEmployee controller, editEmployee.jsp and manageEmployees.jsp views.  For Employee files, I’ll only point out the major differences from the corresponding Department classes above.

/src/main/java/com/technologicaloddity/controller/ManageEmployeesController.java

package com.technologicaloddity.departments.controller;

import java.util.*;

import org.springframework.beans.factory.annotation.*;
import org.springframework.stereotype.*;
import org.springframework.web.bind.annotation.*;

import com.technologicaloddity.departments.dao.*;
import com.technologicaloddity.departments.model.*;

@Controller
public class ManageEmployeesController {

    @Autowired
    private EmployeeDao employeeDao;

    @ModelAttribute("employees")
    public List<Employee> getEmployees() {
        return employeeDao.findAll();
    }

    @RequestMapping("/manageEmployees.html")
    public String handleRequest() {
        return "manageEmployees";
    }
}

Comments on ManageEmployeesController.java: This works exactly like ManageDepartmentsController.  Only the DAO and the @RequestMapping have changed.

/src/main/webapp/WEB-INF/jsp/manageEmployees.jsp

<%@ include file="/WEB-INF/jsp/include.jsp" %>
<html>
<head>
<title>Manage Employees</title>
<link rel="stylesheet" href="<c:url value='/css/departments.css'/>" type="text/css" >
<script type="text/javascript">
function confirmDelete(employeeId) {
    var answer = confirm("Delete this employee?");
    if(answer) {
        document.location.href="<c:url value='/deleteEmployee.html'/>?id=" + employeeId;
    }
}

</script>
</head>
<body>
<h1>Manage Employees</h1>
<hr>
<table width="60%">
<c:choose>
<c:when test="${empty employees}">
    <tr>
        <td colspan="5">No employees were found</td>
    </tr>
</c:when>
<c:otherwise>
    <tr class="tableheader">
        <th>Employee ID</th>
        <th>First Name</th>
        <th>Last Name</th>
        <th>Departments</th>
        <th>Functions</th>
    </tr>
    <c:forEach items="${employees}" var="employee" varStatus="status">
        <tr class="row${status.index % 2 }">
            <td>${employee.id}</td>
            <td>${employee.firstName}</td>
            <td>${employee.lastName}</td>
            <td>
            <c:choose>
                <c:when test="${empty employee.departments}">
                [None]
                </c:when>
                <c:otherwise>
                    <c:forEach items="${employee.departments}" var="department">
                    ${department.name}<br/>
                    </c:forEach>
                </c:otherwise>
            </c:choose>
            </td>
            <td><a href="<c:url value='/editEmployee.html'><c:param name='id' value='${employee.id}'/><c:param name='action' value='edit'/></c:url>">Edit</a>  <a href="javascript:void(0);" onclick="confirmDelete('${employee.id}');">Delete</a></td>
        </tr>
    </c:forEach>
</c:otherwise>
</c:choose>
<tr style="margin-top:20px;">
    <td>&nbsp;</td>
    <td colspan="2"><button onclick="document.location.href='<c:url value='/editEmployee.html'><c:param name='action' value='edit'/></c:url>';">Add new employee</button></td>
</tr>
<tr style="margin-top:20px">
    <td>&nbsp;</td>
    <td><button onclick="document.location.href='<c:url value='/index.html'/>';">Home</button></td>
</tr>
</table>
</body>
</html>

Comments on manageEmployees.jsp:

  • Line 40-49: For employees, we show a list of Departments to which they belong directly on the list.  This is simple, just an iteration over the employee.departments Set.

/src/main/java/com/technologicaloddity/departments/controller/EditEmployee.java

package com.technologicaloddity.departments.controller;

import java.util.*;

import org.springframework.beans.factory.annotation.*;
import org.springframework.stereotype.*;
import org.springframework.validation.*;
import org.springframework.web.bind.*;
import org.springframework.web.bind.annotation.*;

import com.technologicaloddity.departments.dao.*;
import com.technologicaloddity.departments.model.*;

@Controller
@RequestMapping("/editEmployee.html")
public class EditEmployee extends MappedModelFormController<Employee> {

    @Autowired
    private DepartmentDao departmentDao;
    @Autowired
    private DepartmentPropertyEditor deparmentPropertyEditor;

    @Override
    public Class<Employee> getActualClass() {
        return Employee.class;
    }

    @ModelAttribute("allDepartments")
    public List<Department> getAllDepartments() {
        return departmentDao.findAll();
    }

    @InitBinder
    public void initBinder(WebDataBinder dataBinder) {
        dataBinder.registerCustomEditor(Department.class, "departments", deparmentPropertyEditor);
    }

    @Override
    @Autowired
    @Qualifier("employeeValidator")
    public void setMappedModelValidator(Validator validator) {
        this.validator = validator;
    }

    @Override
    @Autowired
    @Qualifier("employeeDao")
    public void setModelDao(MappedModelDao<Employee> modelDao) {
        this.modelDao = modelDao;
    }

}

EditEmployee is quite similar to EditDepartment, with the same setModelDao, getActualClass, and setMappedModelValidator methods.  A few differences are worth pointing out:

  • Line 19: EditEmployee will need a DepartmentDao of it’s own, since you can select Departments to which an Employee belongs on the editEmployee.jsp page.
  • Line 21: Since we will be selecting Departments for an Employee, we need to tell Spring how to bind those to Department objects.  On screen, the Departments will be simple checkboxes with the Department name next to them.  In the database, however, they must be real Department object.  We create this mapping with a Spring PropertyEditor.  We’ll look at DepartmentPropertyEditor after this controller.
  • Lines 28-31: We’ll need a list of all existing departments on the Edit Employee page, so that we can select which departments the Employee belongs to.  We do this with a @ModelAttribute annotation on a method that returns a List of all departments.
  • Lines 33-36: Since we are using a PropertyEditor to bind Departments to the form, we have to initialize that PropertyEditor.  We do this with an @InitBinder annotation on the initBinder method.  The initBinder method simply registers the PropertyEditor for the Department.class, for member “departments” (that is, employee.departments).

Since the PropertyEditor is the new piece of the puzzle, let’s look at that next.

/src/main/java/com/technologicaloddity/departments/model/DepartmentPropertyEditor.java

package com.technologicaloddity.departments.model;

import java.beans.*;

import org.springframework.beans.factory.annotation.*;
import org.springframework.stereotype.*;

import com.technologicaloddity.departments.dao.*;

@Component
public class DepartmentPropertyEditor extends PropertyEditorSupport {

    @Autowired
    private DepartmentDao departmentDao;

    @Override
    public String getAsText() {
        String result = null;
        Department department = (Department)getValue();
        if(department != null) {
            result =  department.getId();
        }
        return result;
    }

    @Override
    public void setAsText(String text) throws IllegalArgumentException {
        Department result = null;
        if(text != null && text.length() > 0) {
            result = departmentDao.findById(text);
        }
        setValue(result);
    }

}

DepartmentPropertyEditor comments:

  • Line 10: Like the DAO objects, we need to @Autowire this DepartmentPropertyEditor later (specifically into EditEmployee.java as we saw above).  Therefore, we make this class a @Component.
  • Line 11: We extend java.beans.PropertyEditorSupport, which provides much of the code without help from us.  We need only implement getAsText and setAsText.
  • Lines 16-24: getAsText() provides us (via Spring) with an Object (through the getValue method), and expects a String in return.  Spring uses that String as the value of the Object inside the end-user form.  For a Department, we want the value to be the ID of the Department, so that is what we return.
  • Lines 26-33: setAsText() is the opposite of getAsText.  Spring calls setAsText with the Department ID as the String parameter.  Our function must setValue() to the actual object, in this case the actual Department.  We use the DepartmentDao to find the Department from the String.  Spring then uses the actual object when binding the form to the final object that is passed into the @ModelAttribute of MappedModelFormController.handleSubmit.

So, in case that wasn’t entirely clear, when the JSP is rendered, Spring will call getAsText() for each Department that we want to map onto the form.  It does this because the form, in the end, is simple HTML.  And placing a Department object on an HTML form doesn’t make any sense (how would you?)  So it puts the ID from getAsText() there instead.  When the form is submitted, but before it is bound or validated, Spring will call setAsText with the value it got from getAsText to convert back to the original object.

We also use an EmployeeValidator inside EditEmployee.

/src/main/java/com/technologicaloddity/departments/validator/EmployeeValidator.java

package com.technologicaloddity.departments.validator;

import org.springframework.stereotype.*;
import org.springframework.util.*;
import org.springframework.validation.*;

import com.technologicaloddity.departments.model.*;

@Component
public class EmployeeValidator implements Validator {

    public boolean supports(Class<?> clazz) {
        return clazz.isAssignableFrom(Employee.class);
    }

    public void validate(Object command, Errors errors) {
        Employee employee = (Employee)command;
        if(!StringUtils.hasText(employee.getFirstName())) {
            errors.rejectValue("firstName", "error.required.firstName", "First Name is required");
        }
        if(!StringUtils.hasText(employee.getLastName())) {
            errors.rejectValue("lastName", "error.required.lastName", "Last Name is required");
        }
    }
}

Comments on EmployeeValidator:

  • EmployeeValidator is almost identical to DepartmentValidator.
  • Employees must have a first and last name to be validated.

And to finish off edit employee, lets look at the view.  Here’s a reminder of what we are trying to do.

depts-editEmployee

/src/main/webapp/WEB-INF/jsp/editEmployee.jsp

<%@ include file="/WEB-INF/jsp/include.jsp" %>
<jsp:include page="pageHeader.jsp" flush="true"></jsp:include>
<spf:form modelAttribute="mappedModel">
<spf:errors path="*"/>
<table  cellpadding="20">
    <tr style="background-color:#c0c0c0">
        <td>ID</td>
        <td><c:choose><c:when test="${empty mappedModel.id}">[Assigned on save]</c:when><c:otherwise>${mappedModel.id}</c:otherwise></c:choose></td>
    </tr>
    <tr style="background-color:#c0c0c0">
        <td>First Name</td>
        <td><spf:input path="firstName"/><spf:errors path="firstName"/></td>
    </tr>
    <tr style="background-color:#c0c0c0">
        <td>Last Name</td>
        <td><spf:input path="lastName"/><spf:errors path="lastName"/></td>
    </tr>
    <tr>
        <td valign="top">Available Departments</td>
        <td>
            <c:forEach items="${allDepartments}" var="department" varStatus="status">
                <c:set var="hasDept" value="false"/>
                <c:forEach items="${mappedModel.departments}" var="empDept">
                    <c:if test="${empDept.id == department.id}">
                        <c:set var="hasDept" value="true"/>
                    </c:if>
                </c:forEach>
                <input id="departments${status.index+1}" name="departments" value="${department.id}" type="checkbox" <c:if test="${hasDept}">CHECKED</c:if>/><label for="departments${status.index+1}">${department.name}</label><br/>
            </c:forEach>
            <input  type="hidden" value="_on" name="_departments"/>
        </td>
    </tr>
    <tr>
        <td>&nbsp;</td>
        <td><input type="submit" name="submit" value="Save"/>&nbsp;<input type="submit" name="submit" value="Cancel"/></td>
    </tr>
</table>
</spf:form>
<jsp:include page="pageFooter.jsp" flush="true"></jsp:include>

Comments on editEmployee.jsp:

  • Lines 1-2: Like editDepartment.jsp, we’ll use include.jsp and pageHeader.jsp to build the top part of the page.
  • Lines 3-4: We bind the Spring form to the mappedModel object, and print out any errors here.
  • Line 8: Just like editDepartment, we print out the ID or “Assigned on save”.  The ID is never editable.
  • Line 12: The binding for firstName.
  • Line 16: The binding for lastName.
  • Lines 20-31: This requires a bit of explanation.  We want to show a list of all existing departments here (using the @ModelAttribute allDepartments from EditEmployee.java), but we also want any Departments to which the Employees already belong to be checked already.  We do this by iterating over allDepartments, then checking whether there is a match in employee.departments.  If there is, we set the checkbox to checked, otherwise we leave it unchecked.  (Note: I tried for a while to do this with Spring’s checkboxes tag, but could never get the effect I wanted.  If you know how to do this, please leave a comment)
  • Line 30: This hidden field is required by Spring in case no Departments are selected.  If there are no Departments, Spring knows that the list was there (but empty) due to this hidden field.
  • Line 35: “Save” and “Cancel” buttons, just as in editDepartment.jsp.

Whew.  Editing objects in a Spring webapp can be a bit overwhelming, but it is much easier with Spring than without it (as many of you will know already).

Finally, we have only the delete functions to go.  Compared to the edit functions, delete is quite simple.  Just to demonstrate that one Controller can handle multiple URL mappings, we’ll put deleteEmployee and deleteDepartment in the same controller.  These controllers are called from editDepartment.jsp and editEmployee.jsp on the “delete” links.

/src/main/java/com/technologicaloddity/departments/controller/DeletionController.java

package com.technologicaloddity.departments.controller;

import org.springframework.beans.factory.annotation.*;
import org.springframework.stereotype.*;
import org.springframework.web.bind.annotation.*;

import com.technologicaloddity.departments.dao.*;
import com.technologicaloddity.departments.model.*;

@Controller
public class DeletionController {

    @Autowired
    private DepartmentDao departmentDao;
    @Autowired
    private EmployeeDao employeeDao;

    @RequestMapping("/deleteEmployee.html")
    public String deleteEmployee(@RequestParam("id") String id) {
        Employee employee = employeeDao.findById(id);
        if(employee != null) {
            employeeDao.delete(employee);
        }
        return "redirect:/manageEmployees.html";
    }

    @RequestMapping("/deleteDepartment.html")
    public String deleteDepartment(@RequestParam("id") String id) {
        Department department = departmentDao.findById(id);
        if(department != null) {
            departmentDao.delete(department);
        }
        return "redirect:/manageDepartments.html";
    }
}

Line-by-line for DeletionController.java.

  • Lines 1-8: Standard package and import statements.
  • Line 10: Like the other controllers, the DeletionController uses Spring’s @Controller stereotype.
  • Lines 13-16: Since DeletionController will handle both Departments and Employees, we need a DAO for each one.
  • Line 18: This method will handle URL deleteEmployee.html (both GET and POST).
  • Line 19: Notice that we have declared a @RequestParameter for the ID.  By default, @RequestParameters are required, so ID is required here.  If you don’t send the ID as a request parameter, this @RequestMapping will not match, and you’ll get a 404 or 500 error.
  • Lines 20-24: Nothing fancy here.  Look up the Employee by the given ID.  If we find it, delete it with the EmployeeDao.
  • Line 27: This method will handle the URL deleteDepartment.html
  • Lines 27-34: deleteDepartment works exactly like deleteEmployee.  ID is required here, just as it is for deleteEmployee.

And that’s it for the application.  Run it and give it a test drive.  You can make a WAR file by using Maven’s package goal.  That’s “mvn package” if you use the command line, or in Eclipse, right-click on the pom.xml file, and select Run As > Maven Package.  The WAR file will be built in your target directory.

Conclusion

Thanks for reading my tutorial on using Spring and Hibernate with annotations.  I know it was a long one.  It took almost a month to create!  Hopefully you now have a better understanding of how to integration Spring and Hibernate and use them in your own web applications.  As I stated in the beginning, I am no Hibernate master, so if you have ideas for improvements, please feel free to comment.

Some things you might want to try as exercises:

  • Add another kind of Object, such as Address.
  • Add another association between Employees, such as Employee.getManager()
  • Change the validators to check for duplicates before trying to save

Download the full source code of the departments project.

20 thoughts on “Spring and Hibernate with Annotations”

  1. Excellent tutorial! Very high quality, it all works beautifully, and very well explained. Thanks for putting it all together. I’ve tried some other similar tutorials before this but none worked. I was using Spring STS as my dev env, and it was fine, with a little change in the initial project setup.

    Only very minor comment is that jsp directory is not usually inside WEB-INF, but alonside it in webapp directory. As I said, this is very minor, viewed against a small mountain of very well designed/executed code.

    All the best
    Noel

    1. Noel,

      Thanks for the kind comments.

      On the matter of the location of the JSP directory, the developers of Spring use the WEB-INF/jsp location themselves (see http://static.springsource.org/spring/docs/2.5.x/reference/mvc.html#mvc-viewresolver ).

      The reason is for security. End users cannot directly reference any file under the WEB-INF directory (with something like http://yoursite.com/webapp/WEB-INF/foo.jsp ) as this produces an error. However, if you use only /jsp, they can reference http://yoursite.com/webapp/jsp/foo.jsp , in the same way they can access http://yoursite.com/webapp/images/logo.gif .

      Using WEB-INF/jsp allows you to maintain complete control of which JSP is shown when, and keeps the script-kiddies from poking around so much.

      Bob

      1. Hi Bob,
        your explanation about why you put the jsp directory into the WEB-INF directory sounds entirely reasonable to me – thanks for that.

        Noel

  2. Wow! Great Tutorial. I’m just in the process of absorbing everything now. The “step by step” code explanation is great for beginners like me. This has got to be the best maven+spring+hibernate tutorial I have come across yet (and I must have seen them all)

    1. Also, it wasn’t working for me at first. I was getting errors like:

      annotations are not supported in -source 1.3
      (use -source 5 or higher to enable annotations)

      I found that Maven’s default java compiler version is 1.3, and even if you don’t have it installed, you’ll still get the above errors unless you explicitly change this by adding the following code within in pom.xml:

      org.apache.maven.plugins
      maven-compiler-plugin
      2.3.2

      1.5
      1.5

        1. Deepak,

          You are 100% correct. You need to specify source and target 1.5 as you have shown above. I have updated the tutorial and source files to reflect this.

          Good catch, thanks!

          Bob

  3. Great tutorial and I learned a lot from this

    I made some changes (Oracle / combined jdbc.properties into the Spring config file etc) and it all works fine

    Then I tried to add some unit tests, but changed the MappedModelDao to implement an interface (extracted through Eclipse) – as explained in
    http://zenoconsulting.wikidot.com/blog:8#toc9

    As soon as I did this, and rebuilt the war, it failed to start in Tomcat with the following exception:

    SEVERE: Exception sending context initialized event to listener instance of class org.springframework.web.context.ContextLoaderListener
    org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘deletionController’: Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.technologicaloddity.departments.dao.DepartmentDao com.technologicaloddity.departments.controller.DeletionController.departmentDao; nested exception is java.lang.IllegalArgumentException: Can not set com.technologicaloddity.departments.dao.DepartmentDao field com.technologicaloddity.departments.controller.DeletionController.departmentDao to $Proxy21
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:283)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1055)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:511)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:450)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:289)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:286)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:188)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:558)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:842)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:416)
    at org.springframework.web.context.ContextLoader.createWebApplicationContext(ContextLoader.java:261)
    at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:192)
    at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:47)
    at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4701)
    at org.apache.catalina.core.StandardContext$1.call(StandardContext.java:5204)
    at org.apache.catalina.core.StandardContext$1.call(StandardContext.java:5199)
    at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
    at java.util.concurrent.FutureTask.run(FutureTask.java:138)
    at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
    at java.lang.Thread.run(Thread.java:662)
    Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.technologicaloddity.departments.dao.DepartmentDao com.technologicaloddity.departments.controller.DeletionController.departmentDao; nested exception is java.lang.IllegalArgumentException: Can not set com.technologicaloddity.departments.dao.DepartmentDao field com.technologicaloddity.departments.controller.DeletionController.departmentDao to $Proxy21
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:504)
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:84)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:280)
    … 21 more
    Caused by: java.lang.IllegalArgumentException: Can not set com.technologicaloddity.departments.dao.DepartmentDao field com.technologicaloddity.departments.controller.DeletionController.departmentDao to $Proxy21
    at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:146)
    at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:150)
    at sun.reflect.UnsafeObjectFieldAccessorImpl.set(UnsafeObjectFieldAccessorImpl.java:63)
    at java.lang.reflect.Field.set(Field.java:657)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:500)
    … 23 more

    Also, I got a similar exception when trying to run a simple JUnit test in Eclipse
    My Spring knowledge is limited, so any help as to what the problem might be would be appreciated
    Thanks

  4. it works with postgres with quite minimal changes, just add the dependency for the jdbc connector for postgres to pom.xml and change jdbc driver class(dispatch-servlet.xml) to postgres(org.postgresql.Driver) and the db url(to something like jdbc:postgresql://localhost:5432/database ).

    great tutorial, better than most other spring and hibernate tutorials on the net! simple working approach that doesn’t need table creation by hand(so simpler to adapt to postgresql).

  5. Hi,

    This is probably one of the best tutorial that I came across.

    Just one thing, why there is no service layer added in the code or shown. Most of the enterprise applications do have a Service Layer for interacting with DB, I guess.

    Thanks & Regards
    Sunil

  6. One more thing, I have to include the servlet dependency in pom file otherwise the project was not getting run and giving error as “Cannot find class file for javax/servlet/ServletContext”.

    Regards
    Sunil

  7. U truly created a number of outstanding stuff within ur article, “Spring and Hibernate with Annotations | Technological
    Oddity”. I may possibly be coming to ur site soon.
    Thanks a lot ,Steve

  8. Now that I’ve just devoted six hours on your website reading your posts, I’m hooked on your blog.
    I bookmarked it as well so that I can keep up with it on a regular basis.
    Have a look at my web site too and tell me what you think.

  9. Heya i am for the first time here. I came across this board and I find It really useful & it helped me out a lot.
    I hope to give something back and aid others like you helped
    me.

  10. This is very interesting, You are a very skilled blogger. I have joined your
    rss feed and look forward to seeking more of your fantastic
    post. Also, I’ve shared your sitee in my social networks!

    1. Lakhan,

      I’m using a MySQL database. The database is automatically created by Hibernate, since “hibernate.hbm2ddl.auto = update” is in the hibernate.properties. So there is no SQL to show. If you have other questions, feel free to ask.

Leave a Reply

Your email address will not be published. Required fields are marked *