Spring Request Forward Enters the Filter Again

Java is often said to be likewise complicated and to take also long to build simple applications. Nonetheless, Java provides a stable platform with a very mature ecosystem around information technology, which makes it a wonderful selection for developing robust software.

The Spring Framework, i of the many powerful frameworks in the Java ecosystem, comes with a drove of programming and configuration models with a goal to simplify the development of performant and testable applications in Java.

Spring Framework

In this tutorial, we will take the challenge of building a uncomplicated application that volition act as a database of software developers using Bound Framework and the Coffee Persistence API (JPA).

The awarding follows a standard MVC architecture. It volition have a controller (ContractsController class), views (based on Thymeleaf templates), and a model (a Java map object). For the sake of simplicity, we will employ an in-memory database behind JPA to persist information while the awarding is running.

Getting Started with the Spring Framework Tutorial

To build a Spring based application, we will demand to utilize one of the post-obit build tools:

  • Maven
  • Gradle

In this tutorial, we will use Maven. If you are not familiar with either of these tools, an like shooting fish in a barrel way to get started is to download the Jump Tool Suite. The suite is dedicated for Spring Framework, and comes with its ain Eclipse based IDE.

In Spring Tool Suite, we create a new project by selecting "Spring Starter Project" from under the "File > New" bill of fare.

Spring Framework Tutorial

In one case a new project has been created, we will need to edit the Maven configuration file, "pom.xml", and add the following dependencies:

          <dependency> 	<groupId>org.springframework.boot</groupId> 	<artifactId>spring-boot-starter-spider web</artifactId> </dependency> <dependency> 	<groupId>org.springframework.kick</groupId> 	<artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency> <dependency> 	<groupId>org.springframework.boot</groupId> 	<artifactId>spring-boot-starter-information-jpa</artifactId> </dependency> <dependency> 	<groupId>com.h2database</groupId> 	<artifactId>h2</artifactId> </dependency> <dependency> 	<groupId>org.springframework.information</groupId> 	<artifactId>spring-information-eatables</artifactId> </dependency>                  

These listed dependencies will load Spring Kick Spider web, Thymeleaf, JPA, and H2 (which will serve as our in-memory database). All necessary libraries volition exist pulled automatically.

Entity Classes

To exist able to store information nigh developers and their skills, we will need to define two entity classes: "Developer" and "Skill".

Both of these are defined as plain Java classes with some annotations. By adding "@Entity" before the classes, we are making their instances bachelor to JPA. This will go far easier to store and retrieve instances from the persistent information store when needed. Additionally, the "@Id" and "@GeneratedValue" annotations let us to bespeak the unique ID field for the entity and take its value generated automatically when stored in the database.

As a programmer can have many skills, we can define a simple many-to-many relationship using the "@ManyToMany" annotation.

Developer

          @Entity public class Programmer {  	@Id 	@GeneratedValue(strategy=GenerationType.Auto) 	individual long id; 	private String firstName; 	private String lastName; 	private Cord e-mail; 	@ManyToMany 	private List<Skill> skills;  	public Developer() { 		super(); 	}  	public Programmer(String firstName, Cord lastName, Cord email, 			List<Skill> skills) { 		super(); 		this.firstName = firstName; 		this.lastName = lastName; 		this.email = email; 		this.skills = skills; 	}  	public long getId() { 		return id; 	}  	public void setId(long id) { 		this.id = id; 	}  	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 Cord getEmail() { 		return e-mail; 	}  	public void setEmail(Cord email) { 		this.email = electronic mail; 	}  	public List<Skill> getSkills() { 		return skills; 	}  	public void setSkills(List<Skill> skills) { 		this.skills = skills; 	}  	public boolean hasSkill(Skill skill) { 		for (Skill containedSkill: getSkills()) { 			if (containedSkill.getId() == skill.getId()) { 				return true; 			} 		} 		return false; 	}  }                  

Skill

          @Entity public form Skill {     @Id     @GeneratedValue(strategy=GenerationType.AUTO)     individual long id;     private Cord label;     private String description;      public Skill() { 		super();     }      public Skill(String label, String clarification) { 		super(); 		this.label = label; 		this.description = description; 	}  	public long getId() { 		return id; 	}  	public void setId(long id) { 		this.id = id; 	}  	public Cord getLabel() { 		return label; 	}  	public void setLabel(String label) { 		this.characterization = label; 	}  	public String getDescription() { 		return clarification; 	}  	public void setDescription(String description) { 		this.description = clarification; 	}      }                  

Repositories

With JPA we tin can define a very useful DeveloperRepository interface and SkillRepository interface, which allow for easy CRUD operations. These interfaces volition let us to access stored developers and skills through simple method calls, such as:

  • "respository.findAll()": returns all developers
  • "repository.findOne(id)": returns developer with given ID

To create these interfaces, all we need to practice is extend the CrudRepository interface.

Developer Repository

          public interface DeveloperRepository extends CrudRepository<Developer, Long> {  }                  

Skill Repository

          public interface SkillRepository extends CrudRepository<Skill, Long> { 	public List<Skill> findByLabel(String label); }                  

Functionality for the the boosted method "findByLabel "alleged here will be provided automatically by JPA.

Controller

Side by side, we can work on the controller for this awarding. The controller will map request URIs to view templates and perform all necessary processing in between.

          @Controller public form DevelopersController {  	@Autowired 	DeveloperRepository repository;  	@Autowired 	SkillRepository skillRepository;  	@RequestMapping("/developer/{id}") 	public String developer(@PathVariable Long id, Model model) { 		model.addAttribute("programmer", repository.findOne(id)); 		model.addAttribute("skills", skillRepository.findAll()); 		return "developer"; 	}  	@RequestMapping(value="/developers",method=RequestMethod.Go) 	public String developersList(Model model) { 		model.addAttribute("developers", repository.findAll()); 		render "developers"; 	}  	@RequestMapping(value="/developers",method=RequestMethod.POST) 	public String developersAdd(@RequestParam String electronic mail,  						@RequestParam String firstName, @RequestParam Cord lastName, Model model) { 		Developer newDeveloper = new Developer(); 		newDeveloper.setEmail(email); 		newDeveloper.setFirstName(firstName); 		newDeveloper.setLastName(lastName); 		repository.save(newDeveloper);  		model.addAttribute("developer", newDeveloper); 		model.addAttribute("skills", skillRepository.findAll()); 		render "redirect:/developer/" + newDeveloper.getId(); 	}  	@RequestMapping(value="/programmer/{id}/skills", method=RequestMethod.POST) 	public Cord developersAddSkill(@PathVariable Long id, @RequestParam Long skillId, Model model) { 		Skill skill = skillRepository.findOne(skillId); 		Programmer developer = repository.findOne(id);  		if (developer != null) { 			if (!programmer.hasSkill(skill)) { 				developer.getSkills().add together(skill); 			} 			repository.relieve(developer); 			model.addAttribute("developer", repository.findOne(id)); 			model.addAttribute("skills", skillRepository.findAll()); 			return "redirect:/programmer/" + developer.getId(); 		}  		model.addAttribute("developers", repository.findAll()); 		return "redirect:/developers"; 	}  }                  

Mapping of URIs to methods is washed via uncomplicated "@RequestMapping" annotations. In this case, every method of the controller is mapped to a URI.

The model parameter of these methods allows data to be passed to the view. In essence, these are unproblematic maps of keys to values.

Each controller method either returns the name of the Thymeleaf template to be used as view, or a URL in a specific pattern ("redirect:") to redirect to. For instance, the methods "programmer" and "_developersList_" returns the name of a template, while "developersAdd" and "developersAddSkill" return URLs to redirect to.

Inside the controller, the "@Autowired" annotations automatically assigns a valid instance of our divers repository in the respective field. This allows access to relevant data from inside the controller without having to deal with a lot of boilerplate lawmaking.

Views

Finally, nosotros demand to define some templates for the views to exist generated. For this nosotros are using Thymeleaf, a simple templating engine. The model nosotros used in controller methods is available directly inside the templates, i.e. when nosotros enter a contract into "contract" key in a model, we will be able to access the name field as "contract.name" from within the template.

Thymeleaf contains some special elements and attributes that command generation of HTML. They are very intuitive and straightforward. For case, to populate the contents of a span element with the name of a skill, all you need to practise is ascertain the post-obit attribute (assuming that the key "skill" is divers in the model):

          <span th:text="${skill.characterization}"></span>                  

Similarly to set the "href" aspect of an anchor element, the special aspect "th:href" can exist used.

In our application, we will demand two simple templates. For clarity, we will skip all manner and class attributes (namely Bootstrap ones) here in the embedded template code.

Developer List

          <!DOCTYPE HTML> <html xmlns:th="http://www.thymeleaf.org"> <head>  	<championship>Developers database</title>  	<meta http-equiv="Content-Type" content="text/html; charset=UTF-eight" /> </head> <trunk> 	<h1>Developers</h1> 	<tabular array> 		<tr> 			<th>Name</th> 			<th>Skills</th> 			<thursday></th> 		</tr> 		<tr th:each="programmer : ${developers}"> 			<td th:text="${developer.firstName + ' ' + developer.lastName}"></td> 			<td> 				<span thursday:each="skill,iterStat : ${programmer.skills}"> 					<span thursday:text="${skill.label}"/><thursday:cake th:if="${!iterStat.last}">,</thursday:block> 				</span> 			</td> 			<td> 				<a th:href="@{/programmer/{id}(id=${developer.id})}">view</a> 			</td> 		</tr> 	</table> 	<hr/> 	<form th:action="@{/developers}" method="mail" enctype="multipart/course-data"> 		<div> 			Outset name: <input proper name="firstName" /> 		</div> 		<div> 			Last name: <input name="lastName" /> 		</div> 		<div> 			E-mail: <input proper noun="e-mail" /> 		</div> 		<div> 			<input type="submit" value="Create programmer" name="button"/> 		</div> 	</grade> </body> </html>                  

Developer Details

          <!DOCTYPE HTML> <html xmlns:th="http://www.thymeleaf.org"> <head> 	<championship>Developer</championship> 	<meta http-equiv="Content-Blazon" content="text/html; charset=UTF-eight" /> </head> <body> 	<h1>Programmer</h1> 	Proper name: <b th:text="${programmer.firstName}" /> <b th:text="${developer.lastName}" /><br/> 	Electronic mail: <bridge th:text="${developer.email}" /><br/> 	Skills: 		<span thursday:each="skill : ${developer.skills}"> 			<br/>&nbsp;&nbsp;<bridge th:text="${skill.characterization}" /> - <span th:text="${skill.clarification}" /> 		</span> 	<grade th:action="@{/developer/{id}/skills(id=${developer.id})}" method="post" enctype="multipart/form-data" > 		<select name="skillId"> 			<option th:each="skill : ${skills}"  				th:value="${skill.id}"  				th:text="${skill.description}">Skill</option> 		</select> 		<input blazon="submit" value="Add together skill"/> 	</form> </body> </html>                  

Running the Server

Spring contains a boot module. This allows usa to start the server easily from command line as a control line Coffee awarding:

          @SpringBootApplication public grade Application implements CommandLineRunner {      @Autowired     DeveloperRepository developerRepository;      @Autowired     SkillRepository skillRepository;      public static void main(String[] args) {         SpringApplication.run(Application.class, args);     }  }                  

Since nosotros are using an in-memory database, it makes sense to bootstrap the database with some predefined data at launch. That way nosotros will have at least some data in the database when the server is up and running.

          @Override public void run(Cord... args) throws Exception { 	Skill javascript = new Skill("javascript", "Javascript linguistic communication skill"); 	Skill ruby = new Skill("cherry-red", "Red language skill"); 	Skill emberjs = new Skill("emberjs", "Emberjs framework"); 	Skill angularjs = new Skill("angularjs", "Angularjs framework");  	skillRepository.save(javascript); 	skillRepository.save(ruby-red); 	skillRepository.save(emberjs); 	skillRepository.salvage(angularjs);  	List<Developer> developers = new LinkedList<Developer>(); 	developers.add together(new Developer("John", "Smith", "john.smith@example.com",  			Arrays.asList(new Skill[] { javascript, scarlet }))); 	developers.add(new Developer("Marking", "Johnson", "mjohnson@example.com",  			Arrays.asList(new Skill[] { emberjs, ruby }))); 	developers.add(new Developer("Michael", "Williams", "michael.williams@case.com",  			Arrays.asList(new Skill[] { angularjs, ruddy }))); 	developers.add(new Developer("Fred", "Miller", "f.miller@example.com",  			Arrays.asList(new Skill[] { emberjs, angularjs, javascript }))); 	developers.add together(new Developer("Bob", "Chocolate-brown", "dark-brown@example.com",  			Arrays.asList(new Skill[] { emberjs }))); 	developerRepository.save(developers); }                  

Determination

Spring is a versatile framework that allows building MVC applications. Edifice a uncomplicated application with Bound is quick and transparent. The application can also be integrated with a database easily using JPA.

The source code of this entire project is available on GitHub.

straughteraltors.blogspot.com

Source: https://www.toptal.com/spring/beginners-guide-to-mvc-with-spring-framework

0 Response to "Spring Request Forward Enters the Filter Again"

Post a Comment

Iklan Atas Artikel

Iklan Tengah Artikel 1

Iklan Tengah Artikel 2

Iklan Bawah Artikel