Showing posts with label Persistence. Show all posts
Showing posts with label Persistence. Show all posts

Tuesday, 2 April 2013

Creating A Customized Spring User & Persistence

This post explains how to create a customized Spring user and persistence mechanism for authentication. The code is available at GitHub in the Spring-MVC-Customized-User directory.

Things To Take Into Consideration

Before creating a customized user, we need to remind what a user is in Spring. We know from here that a user is an implementation of the UserDetails interface. Spring security also requires a loading mechanism, as an implementation of the UserDetailsService interface. To keep this example simple, we are not going to implement login/logout or other security features.

The UserDetails interface is a bit incomplete in order to define a user in a real application. It defines getters and no setters. It is not a big deal, but the real pain is that the username (a string) is considered as 'the' key. Most software developers will prefer a long id.

To solve these issues, we define a PracticalUser interface:
public interface PracticalUserDetails
        extends UserDetails, CredentialsContainer {

    long getId();

    void setPassword(String password);

    void setAccountExpired(boolean b);

    void setAccountLocked(boolean b);

    void setCredentialsExpired(boolean b);

    void setEnabled(boolean b);

    void setAuthorities(
        Collection<? extends GrantedAuthority> authorities);

}
Typically, one would use JPA annotations on the implementation bean and save it in a database in a real application. However, for this example, the DAO will register users in an in-memory map as described further.

The UserDetailsService interface does not provide a get user per name or id, which is necessary for an administrator (for example). More, it does not allow to retrieve all existing users' id and name, or to update or insert users, or even to delete them.

Therefore, we create a PracticalUserDetailsService interface to solve these issues:
public interface PracticalUserDetailsService
        extends UserDetailsService {

    Set<PracticalUserDetailsDAO.UserIdentifiers> getUsers();

    void deleteUser(long id);

    void upsertUser(PracticalUserDetails user);

    PracticalUserDetails getUser(long id);

    PracticalUserDetails getUser(String username);

}
The corresponding implementation is called PracticalUserDetailsServiceInMemory for this example.

In-Memory DAO

To keep this example simple, we define a simple PracticalUserDetailsDAO:
public interface PracticalUserDetailsDAO<U extends PracticalUserDetails> {

    void create(U user);

    boolean contains(U user);

    U read(String username);

    U read(long id);

    void update(U user);

    void delete(String username);

    void delete(long id);

    interface UserIdentifiers {
        long getId();
        String getUsername();
    }

    Set<UserIdentifiers> getUsers();

}
We also define a special user id and name identifier interface to retrieve the set of existing user data, without returning all users. Our implementation of PracticalUserDetailsDAO is PracticalUserDetailsDAOInMemory.

In a real implementation, using a JPA Repository is more appropriate.

Configuration

In the security.xml file, we define our practical user detail service (it will be registered in the authentication manager) and the in-memory DAO bean:
<beans:beans xmlns="http://www.springframework.org/schema/security"
  xmlns:beans="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
    http://www.springframework.org/schema/security
    http://www.springframework.org/schema/security/spring-security-3.1.xsd">

    <http auto-config="true">
    </http>

    <authentication-manager alias="authenticationManager">
        <authentication-provider user-service-ref='practicalUserDetailsServiceInMemory' />
    </authentication-manager>

    <beans:bean id="pud"
        class="com.jverstry.DAO.PracticalUserDetailsDAOInMemory">
    </beans:bean>

</beans:beans>

The JSP Pages

We use two pages. The main page displays registered users (together with a delete link) and registration form:


The second page is displayed when the Create User button is clicked to check the name and the password:


The Controller

The controller is used to check the username and password:
@Controller
public class MyController {

    @Autowired
    private PracticalUserDetailsServiceInMemory pudm;

    @RequestMapping(value = "/")
    public ModelAndView index() {

        ModelAndView result = new ModelAndView("index");

        result.addObject("users", this.pudm.getUsers());

        return result;

    }

    @RequestMapping(value = "/delete/{id}")
    public String delete(@PathVariable(value="id") String id) {

        this.pudm.deleteUser(Long.parseLong(id));

        return "redirect:/";

    }

    @RequestMapping(value = "/create")
    @SuppressWarnings("AssignmentToMethodParameter")
    public ModelAndView add(
            @RequestParam(value="name")
            String name,
            @RequestParam(value="password")
            String password) {

        name = StringUtils.replace(name, " ", "");
        password = StringUtils.replace(password, " ", "");

        String errorMsg = "";

        if ( name.length() == 0 ) {
            errorMsg += "Name is empty ";
        }

        if ( password.length() == 0 ) {
            errorMsg += "Password is empty ";
        }

        if ( errorMsg.isEmpty() ) {
            this.pudm.upsertUser(new PracticalUserDetailsImpl(name, password));
        }

        ModelAndView result = new ModelAndView("create");

        result.addObject("errorMsg", errorMsg);
        result.addObject("username", name);

        return result;

    }

}

Running The Example

One can run it using the maven tomcat:run goal. Then, browse:

  http://localhost:9191/spring-mvc-customized-user/

More Spring related posts here.

Monday, 3 September 2012

Spring MVC-Service-DAO-Persistence Architecture Example

It is considered good practice to use modularity across Spring web applications. It keeps them maintainable and testable. This can be achieved by using controllers, services and data access objects (DAO). Typically, a user request is handled by a controller, which calls a service, which calls a data access object, which calls the persistence layer implementation.

Using services means that application functionalities can be tested without a test framework simulating user calls to controllers. Separating services from the persistence layer implementation via DAO, allows using an in-memory database (for example) by substituting production DAO implementations, by test DAO implementation pointing to an in-memory database.

The code example used in this post is available from Github in the Spring-MVC-Service-DAO-Persistence-Architecture directory. It is a variation of the Spring Web JPA Hibernate In-Memory example.

MVC Controller Calls The Service Implementation

The following controller is injected with an implementation of MyService. It handles /roundtrip user calls by calling its create() and Retrieve(id) methods, which creates and retrieves an instance of a MilliTimeItem object. It contains a unique ID and a timestamp in milliseconds.
@Controller
public class MyController {

    @Autowired
    private MyService myService;

    @RequestMapping(value = "/")
    public String home(Model model) {
        return "index";
    }

    @RequestMapping(value = "/roundtrip")
    public String persistenceStatus(Model model) {

        long id = myService.create();
        MilliTimeItem retr = myService.retrieve(id);
 
        model.addAttribute("RoundTrip", retr);
 
        return "roundtrip";

    }

}

Service Implementation calls Data Access Objects (DAO)

The DAO is injected in the MyService implementation. The createAndRetrieve() calls the DAO createMilliTimeItem() and getMilliTimeItem() methods. It returns the created and retrieved item.
public class MyServiceImpl implements MyService {

    @Autowired
    private MyPersistenceDAO myDAO;

    @Transactional
    long create();
 
    @Transactional
    MilliTimeItem retrieve(long id);

}

Data Access Object Implementation Calls The Persistence Layer

The DAO implementation is injected with the JPA EntityManager:
@Repository
public class MyPersistenceDAOImpl implements MyPersistenceDAO {

    @PersistenceContext
    private EntityManager em;

    @Override
    public long createMilliTimeItem() {
 
        MilliTimeItem mti = new MilliTimeItem();
        mti.setMilliTime(System.currentTimeMillis());

        em.persist(mti);
        long result = mti.getID();
        em.detach(mti);
 
        return result;
 
    }

    @Override
    public MilliTimeItem getMilliTimeItem(long id) {
        return em.find(MilliTimeItem.class, id);
    }

}

Running the Example

After compiling this example with Maven, it can be run with mvn tomcat:run. Then, browse http://localhost:8585/spring-mvc-service-dao-persistence-architecture/.

The generated output is:
Created MilliTimeItem's ID: 1
Created MilliTimeItem's value: 1346691836108

More Spring related posts here.