Review
In the previous section, we declared our configuration using JavaConfig and compared it side-by-side with an XML-based configuration. In this section, we will discuss the remaining layers of our application.
Table of Contents
Click on a link to jump to that section:
- Functional Specs
- Creating the View
- HTML Mockup
- Thymeleaf Integration
- JavaConfig
- ApplicationContext.java
- SpringDataConfig.java
- ThymeleafConfig.java
- ApplicationInitializer.java
- Layers
- Domain
- Service
- Controller
- Running the application
- Clone from GitHub
- Create the Database
- Run with Maven and Tomcat 7
- Run with Maven and Jetty 8
- Import to Eclipse
- Validate with W3C
Layers
Here we'll discuss the Domain, Repository, Service and Controller layers.
Domain
Our domain layer consists of two simple classes: User.java and Role.java. If you'd been following my previous tutorials, you will notice that these are the same domain classes we'd been using before. Both classes had been annotated with @Entity which means these are JPA entities and will be persisted to a database.These classes represent a user with the following properties: first name, last name, username, role, and password (we're not actively using the password field).
For role, we only have two values: an admin or a regular user.
User.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package org.krams.domain; | |
import javax.persistence.CascadeType; | |
import javax.persistence.Column; | |
import javax.persistence.Entity; | |
import javax.persistence.GeneratedValue; | |
import javax.persistence.GenerationType; | |
import javax.persistence.Id; | |
import javax.persistence.OneToOne; | |
import org.codehaus.jackson.annotate.JsonManagedReference; | |
@Entity(name="user") | |
public class User { | |
@Id | |
@GeneratedValue(strategy = GenerationType.AUTO) | |
private Long id; | |
private String firstName; | |
private String lastName; | |
@Column(unique=true) | |
private String username; | |
private String password; | |
@JsonManagedReference | |
@OneToOne(mappedBy="user", cascade={CascadeType.ALL}) | |
private Role role; | |
public User() {} | |
...getters/setters... | |
} |
Role.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package org.krams.domain; | |
import javax.persistence.Entity; | |
import javax.persistence.GeneratedValue; | |
import javax.persistence.GenerationType; | |
import javax.persistence.Id; | |
import javax.persistence.OneToOne; | |
import org.codehaus.jackson.annotate.JsonBackReference; | |
@Entity(name="role") | |
public class Role { | |
@Id | |
@GeneratedValue(strategy = GenerationType.AUTO) | |
private Long id; | |
@JsonBackReference | |
@OneToOne | |
private User user; | |
private Integer role; | |
public Role() {} | |
...getters/setters... | |
} |
Controller
Our controller is a standard controller providing CRUD requests. The most important lines here are the following:// Create
model.addAttribute("users", UserMapper.map(users));
model.addAttribute("commanduser", new UserDto());
model.addAttribute("usertype", "new");
model.addAttribute("users", UserMapper.map(users));
model.addAttribute("commanduser", new UserDto());
model.addAttribute("usertype", "new");
// Update
model.addAttribute("users", UserMapper.map(users));
model.addAttribute("commanduser", UserMapper.map(repository.findOne(id)));
model.addAttribute("usertype", "update");
model.addAttribute("users", UserMapper.map(users));
model.addAttribute("commanduser", UserMapper.map(repository.findOne(id)));
model.addAttribute("usertype", "update");
These lines adds three attributes to the model:
- users - contains all users
- commanduser - the form backing object or the command object of the form
- usertype - an attribute to determine if the request is a new user or existing user
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package org.krams.controller; | |
import java.util.ArrayList; | |
import java.util.List; | |
import org.krams.domain.Role; | |
import org.krams.domain.User; | |
import org.krams.repository.UserRepository; | |
import org.krams.response.UserDto; | |
import org.krams.service.UserService; | |
import org.krams.util.UserMapper; | |
import org.springframework.beans.factory.annotation.Autowired; | |
import org.springframework.data.domain.Page; | |
import org.springframework.data.domain.PageRequest; | |
import org.springframework.data.domain.Pageable; | |
import org.springframework.stereotype.Controller; | |
import org.springframework.web.bind.annotation.ModelAttribute; | |
import org.springframework.web.bind.annotation.RequestBody; | |
import org.springframework.web.bind.annotation.RequestMapping; | |
import org.springframework.web.bind.annotation.RequestMethod; | |
import org.springframework.web.bind.annotation.ResponseBody; | |
import org.springframework.ui.ModelMap; | |
@Controller | |
@RequestMapping("/users") | |
public class UserController { | |
@Autowired | |
private UserRepository repository; | |
@Autowired | |
private UserService service; | |
@ModelAttribute("allRoles") | |
public List<Integer> getAllRoles() { | |
List<Integer> roles = new ArrayList<Integer>(); | |
roles.add(1); | |
roles.add(2); | |
return roles; | |
} | |
@RequestMapping | |
public String getUsersPage(ModelMap model) { | |
Pageable pageRequest = new PageRequest(0, 10); | |
Page<User> users = repository.findAll(pageRequest); | |
model.addAttribute("users", UserMapper.map(users)); | |
model.addAttribute("commanduser", new UserDto()); | |
model.addAttribute("usertype", "new"); | |
return "users"; | |
} | |
@RequestMapping(value="/get", produces="application/json") | |
public @ResponseBody UserDto get(@RequestBody UserDto user) { | |
return UserMapper.map(repository.findByUsername(user.getUsername())); | |
} | |
@RequestMapping(value="/create", produces="application/json", method=RequestMethod.POST) | |
public String create(UserDto dto) { | |
if (dto.getId() != null) { | |
User existingUser = new User(dto.getUsername(), | |
dto.getFirstName(), | |
dto.getLastName(), | |
new Role(dto.getRole())); | |
service.update(existingUser); | |
} else { | |
User newUser = new User(dto.getUsername(), | |
null, | |
dto.getFirstName(), | |
dto.getLastName(), | |
new Role(dto.getRole())); | |
service.create(newUser); | |
} | |
return "redirect:/users"; | |
} | |
@RequestMapping(value="/edit") | |
public String edit(Long id, ModelMap model) { | |
Pageable pageRequest = new PageRequest(0, 10); | |
Page<User> users = repository.findAll(pageRequest); | |
model.addAttribute("users", UserMapper.map(users)); | |
model.addAttribute("commanduser", UserMapper.map(repository.findOne(id))); | |
model.addAttribute("usertype", "update"); | |
return "users"; | |
} | |
@RequestMapping(value="/delete") | |
public String delete(Long id) { | |
User existingUser = new User(); | |
existingUser.setId(id); | |
service.delete(existingUser); | |
return "redirect:/users"; | |
} | |
} |
Repository
We have created two repositories: UserRepository and RoleRepository(not shown). We will be using UserRepository as our primary data access object. Notice we have declared a custom method findByUsername but beyond that, this repository is pretty much standard. UserRepository.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package org.krams.repository; | |
import org.krams.domain.User; | |
import org.springframework.data.jpa.repository.JpaRepository; | |
public interface UserRepository extends JpaRepository<User, Long> { | |
User findByUsername(String username); | |
} |
Service
Our service layer basically delegates to the repository. It provides an extra logic to filter out duplicate usernames. UserService.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package org.krams.service; | |
import org.krams.domain.User; | |
import org.krams.repository.UserRepository; | |
import org.springframework.beans.factory.annotation.Autowired; | |
import org.springframework.stereotype.Service; | |
import org.springframework.transaction.annotation.Transactional; | |
@Service | |
@Transactional | |
public class UserService { | |
@Autowired | |
private UserRepository repository; | |
public Boolean create(User user) { | |
User existingUser = repository.findByUsername(user.getUsername()); | |
if (existingUser != null) | |
return false; | |
user.getRole().setUser(user); | |
User saved = repository.save(user); | |
if (saved == null) | |
return false; | |
return true; | |
} | |
public Boolean update(User user) { | |
User existingUser = repository.findByUsername(user.getUsername()); | |
if (existingUser == null) | |
return false; | |
// Only firstName, lastName, and role fields are updatable | |
existingUser.setFirstName(user.getFirstName()); | |
existingUser.setLastName(user.getLastName()); | |
existingUser.getRole().setRole(user.getRole().getRole()); | |
User saved = repository.save(existingUser); | |
if (saved == null) | |
return false; | |
return true; | |
} | |
public Boolean delete(User user) { | |
User existingUser = repository.findOne(user.getId()); | |
if (existingUser == null) | |
return false; | |
repository.delete(existingUser); | |
User deletedUser = repository.findOne(user.getId()); | |
if (deletedUser != null) | |
return false; | |
return true; | |
} | |
} |
Next
In the next section, we will study how to build and run our application. We will be using Maven, Tomcat, and Jetty to run the app. We'll also study how to import the project in Eclipse. Click here to proceed.
Share the joy:
![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() |


superb. Thank you!
ReplyDelete