Search with Spring Data JPA in Struts 2

On the Eclipse, create a Maven project

Click Next button and select Workspace location for project

Click Next button and select maven-archetype-webapp

Click Next button and enter Project Information:

  • GroupId: LearnStrutsFrameworkWithRealApps
  • Artifact Id: LearnStrutsFrameworkWithRealApps
  • Package: com.demo

Click Finish button to finish create Maven project




Select current project, Right click and select Properties menu. In Properties dialog, select Targeted Runtime in left side after select Tomcat server from server list in right side

Click Ok button to finish

Select current project, Right click and select Build Path\Configure Build Path menu Select JRE System Library in Libraries tab:

Click Edit button and select JRE System Library you need use as below:

Click Finish button to finish




Open pom.xml file and add configurations for Struts 2 as below:

<project xmlns="http://maven.apache.org/POM/4.0.0"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>LearnStrutsFrameworkWithRealApps</groupId>
	<artifactId>LearnStrutsFrameworkWithRealApps</artifactId>
	<packaging>war</packaging>
	<version>0.0.1-SNAPSHOT</version>
	<name>LearnStrutsFrameworkWithRealApps Maven Webapp</name>
	<url>http://maven.apache.org</url>
	<dependencies>

		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>3.8.1</version>
			<scope>test</scope>
		</dependency>

		<!-- JSTL -->

		<dependency>
			<groupId>javax.servlet.jsp.jstl</groupId>
			<artifactId>javax.servlet.jsp.jstl-api</artifactId>
			<version>1.2.1</version>
		</dependency>

		<dependency>
			<groupId>taglibs</groupId>
			<artifactId>standard</artifactId>
			<version>1.1.2</version>
		</dependency>

		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>javax.servlet-api</artifactId>
			<version>3.1.0</version>
			<scope>provided</scope>
		</dependency>

		<!-- MySQL Driver -->

		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<version>8.0.15</version>
		</dependency>

		<!-- Spring Data JPA -->

		<dependency>
			<groupId>org.springframework.data</groupId>
			<artifactId>spring-data-jpa</artifactId>
			<version>2.1.5.RELEASE</version>
		</dependency>

		<dependency>
			<groupId>javax.persistence</groupId>
			<artifactId>javax.persistence-api</artifactId>
			<version>2.2</version>
		</dependency>

		<dependency>
			<groupId>org.hibernate</groupId>
			<artifactId>hibernate-entitymanager</artifactId>
			<version>5.4.1.Final</version>
		</dependency>

		<!-- Struts 2 Framework -->

		<dependency>
			<groupId>org.apache.struts</groupId>
			<artifactId>struts2-core</artifactId>
			<version>2.5.20</version>
		</dependency>

		<dependency>
			<groupId>org.apache.struts</groupId>
			<artifactId>struts2-convention-plugin</artifactId>
			<version>2.5.20</version>
		</dependency>

		<dependency>
			<groupId>org.apache.struts</groupId>
			<artifactId>struts2-spring-plugin</artifactId>
			<version>2.5.20</version>
		</dependency>

		<!-- Spring Framework -->

		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-core</artifactId>
			<version>5.1.5.RELEASE</version>
		</dependency>

		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-beans</artifactId>
			<version>5.1.5.RELEASE</version>
		</dependency>

		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>5.1.5.RELEASE</version>
		</dependency>

		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context-support</artifactId>
			<version>5.1.5.RELEASE</version>
		</dependency>

		<dependency>
			<groupId>org.springframework.security</groupId>
			<artifactId>spring-security-core</artifactId>
			<version>5.1.4.RELEASE</version>
		</dependency>

		<dependency>
			<groupId>org.springframework.security</groupId>
			<artifactId>spring-security-taglibs</artifactId>
			<version>5.1.4.RELEASE</version>
		</dependency>

		<dependency>
			<groupId>org.springframework.security</groupId>
			<artifactId>spring-security-web</artifactId>
			<version>5.1.4.RELEASE</version>
		</dependency>

		<dependency>
			<groupId>org.springframework.security</groupId>
			<artifactId>spring-security-config</artifactId>
			<version>5.1.4.RELEASE</version>
		</dependency>

		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-web</artifactId>
			<version>5.1.5.RELEASE</version>
		</dependency>

	</dependencies>
	<build>
		<finalName>LearnStrutsFrameworkWithRealApps</finalName>
	</build>
</project>




Open web.xml file in src\main\webapp\WEB-INF folder and add configurations for Struts 2 as below:

<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
		 http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
	version="3.1">

	<display-name>Learn Struts 2 Framework with Real Apps</display-name>

	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>com.demo.config.AppConfig</param-value>
	</context-param>

	<context-param>
		<param-name>contextClass</param-name>
		<param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
	</context-param>

	<filter>
		<filter-name>struts2</filter-name>
		<filter-class>org.apache.struts2.dispatcher.filter.StrutsPrepareAndExecuteFilter</filter-class>
		<init-param>
			<param-name>struts.devMode</param-name>
			<param-value>true</param-value>
		</init-param>
		<init-param>
			<param-name>struts.action.extension</param-name>
			<param-value>html</param-value>
		</init-param>
	</filter>

	<filter-mapping>
		<filter-name>struts2</filter-name>
		<url-pattern>/*</url-pattern>
		<dispatcher>REQUEST</dispatcher>
		<dispatcher>FORWARD</dispatcher>
		<dispatcher>INCLUDE</dispatcher>
	</filter-mapping>

	<welcome-file-list>
		<welcome-file>index.jsp</welcome-file>
	</welcome-file-list>

	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>

</web-app>

Create a database with the name is learn_strust2_with_real_apps. This database have a table: Product table

--
-- Table structure for table `product`
--

CREATE TABLE `product` (
  `id` int(11) NOT NULL,
  `name` varchar(250) COLLATE utf8_unicode_ci NOT NULL,
  `price` double NOT NULL,
  `quantity` int(11) NOT NULL,
  `description` text COLLATE utf8_unicode_ci NOT NULL,
  `status` tinyint(1) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

--
-- Dumping data for table `product`
--

INSERT INTO `product` (`name`, `price`, `quantity`, `description`, `status`) VALUES('Mobile 2', '1.0', 5, 'description 2', 1);
INSERT INTO `product` (`name`, `price`, `quantity`, `description`, `status`) VALUES('Mobile 1', '2.0', 2, 'description 1', 1);
INSERT INTO `product` (`name`, `price`, `quantity`, `description`, `status`) VALUES('Mobile 3', '3.0', 9, 'description 3', 1);
INSERT INTO `product` (`name`, `price`, `quantity`, `description`, `status`) VALUES('Computer 1', '5.0', 12, 'description 4', 0);
INSERT INTO `product` (`name`, `price`, `quantity`, `description`, `status`) VALUES('Computer 2', '7.0', 5, 'description 5', 1);
INSERT INTO `product` (`name`, `price`, `quantity`, `description`, `status`) VALUES('Computer 3', '12.0', 2, 'description 6', 1);
INSERT INTO `product` (`name`, `price`, `quantity`, `description`, `status`) VALUES('Laptop 1', '3.0', 8, 'description 7', 0);
INSERT INTO `product` (`name`, `price`, `quantity`, `description`, `status`) VALUES('Laptop 2', '4.0', 11, 'description 8', 0);
INSERT INTO `product` (`name`, `price`, `quantity`, `description`, `status`) VALUES('Laptop 3', '2.0', 15, 'description 9', 1);




Create new package named com.demo.entities. In this package, create new java class named Product.java as below:

package com.demo.entities;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name = "product")
public class Product {

	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	private int id;

	@Column
	private String name;

	@Column
	private double price;

	@Column
	private int quantity;

	@Column
	private String description;

	@Column
	private boolean status;

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public double getPrice() {
		return price;
	}

	public void setPrice(double price) {
		this.price = price;
	}

	public int getQuantity() {
		return quantity;
	}

	public void setQuantity(int quantity) {
		this.quantity = quantity;
	}

	public String getDescription() {
		return description;
	}

	public void setDescription(String description) {
		this.description = description;
	}

	public boolean isStatus() {
		return status;
	}

	public void setStatus(boolean status) {
		this.status = status;
	}

}

Create new package named com.demo.repositories. In this package, create new java interface named ProductRepository.java as below:

package com.demo.repositories;

import java.util.List;

import com.demo.entities.Product;

public interface ProductRepository {

	public List<Product> findAll();

	public List<Product> search(String keyword);

}




In com.demo.repositories package, create new java class named ProductRepositoryImpl.java as below:

package com.demo.repositories;

import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

import com.demo.entities.Product;

public class ProductRepositoryImpl implements ProductRepository {

	@PersistenceContext
	private EntityManager entityManager;

	@SuppressWarnings("unchecked")
	public List<Product> findAll() {
		try {
			return entityManager.createQuery("from Product").getResultList();
		} catch (Exception e) {
			return null;
		}
	}

	@SuppressWarnings("unchecked")
	public List<Product> search(String keyword) {
		try {
			return entityManager.createQuery("from Product where name like :keyword")
								.setParameter("keyword", "%" + keyword + "%")
								.getResultList();
		} catch (Exception e) {
			return null;
		}
	}

}

Create new package named com.demo.services. In this package, create new java interface named ProductService.java as below:

package com.demo.services;

import java.util.List;

import com.demo.entities.Product;

public interface ProductService {

	public List<Product> findAll();

	public List<Product> search(String keyword);

}

In com.demo.services package, create new java class named ProductServiceImpl.java as below:

package com.demo.services;

import java.util.List;

import org.springframework.transaction.annotation.Transactional;

import com.demo.entities.Product;
import com.demo.repositories.ProductRepository;

@Transactional
public class ProductServiceImpl implements ProductService {

	private ProductRepository productRepository;

	public ProductServiceImpl(ProductRepository productRepository) {
		this.productRepository = productRepository;
	}

	public List<Product> findAll() {
		return this.productRepository.findAll();
	}

	public List<Product> search(String keyword) {
		return this.productRepository.search(keyword);
	}

}




Create new package named com.demo.config. In this package, create new java class named AppConfig.java as below:

package com.demo.config;

import java.util.Properties;

import javax.persistence.EntityManagerFactory;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.JpaVendorAdapter;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;

import com.demo.repositories.ProductRepository;
import com.demo.repositories.ProductRepositoryImpl;
import com.demo.services.ProductService;
import com.demo.services.ProductServiceImpl;

@Configuration
@ComponentScan("com.demo")
@EnableTransactionManagement
public class AppConfig {

	@Bean(name = "entityManager")
	public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
		LocalContainerEntityManagerFactoryBean entityManager = new LocalContainerEntityManagerFactoryBean();
		entityManager.setDataSource(dataSource());
		entityManager.setPackagesToScan(new String[] { "com.demo.entities" });

		JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
		entityManager.setJpaVendorAdapter(vendorAdapter);
		entityManager.setJpaProperties(additionalProperties());

		return entityManager;
	}

	@Bean
	public DriverManagerDataSource dataSource() {
		DriverManagerDataSource dataSource = new DriverManagerDataSource();
		dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
		dataSource.setUrl("jdbc:mysql://localhost:3306/learn_strust2_with_real_apps");
		dataSource.setUsername("root");
		dataSource.setPassword("123456");
		return dataSource;
	}

	@Bean
	public PlatformTransactionManager transactionManager(EntityManagerFactory emf) {
		JpaTransactionManager transactionManager = new JpaTransactionManager();
		transactionManager.setEntityManagerFactory(emf);
		return transactionManager;
	}

	@Bean
	public PersistenceExceptionTranslationPostProcessor exceptionTranslation() {
		return new PersistenceExceptionTranslationPostProcessor();
	}

	public Properties additionalProperties() {
		Properties properties = new Properties();
		properties.setProperty("hibernate.dialect", "org.hibernate.dialect.MySQL5Dialect");
		return properties;
	}

	@Bean(name = "productRepository")
	public ProductRepository productRepository() {
		return new ProductRepositoryImpl();
	}

	@Bean(name = "productService")
	public ProductService productService() {
		return new ProductServiceImpl(productRepository());
	}

}




Create new package named com.demo.controllers.action in src/main/java folder. The action class in Struts 2 must be put in a package named action. In this package, create new java class named ProductAction.java as below:

package com.demo.controllers.action;

import java.util.List;

import org.apache.struts2.convention.annotation.Action;
import org.apache.struts2.convention.annotation.Namespace;
import org.apache.struts2.convention.annotation.Result;
import org.springframework.beans.factory.annotation.Autowired;

import com.demo.entities.Product;
import com.demo.services.ProductService;
import com.opensymphony.xwork2.ActionSupport;

@Namespace("/product")
public class ProductAction extends ActionSupport {

	private static final long serialVersionUID = 1L;

	@Autowired
	private ProductService productService;

	private String keyword;
	private List<Product> products;

	public String getKeyword() {
		return keyword;
	}

	public void setKeyword(String keyword) {
		this.keyword = keyword;
	}

	public List<Product> getProducts() {
		return products;
	}

	public void setProducts(List<Product> products) {
		this.products = products;
	}

	@Action(value = "index", results = {
		@Result(name = SUCCESS, location = "/WEB-INF/views/product/index.jsp")
	})
	public String index() {
		this.products = this.productService.findAll();
		return SUCCESS;
	}

	@Action(value = "search", results = {
		@Result(name = SUCCESS, location = "/WEB-INF/views/product/index.jsp")
	})
	public String search() {
		this.products = this.productService.search(keyword);
		return SUCCESS;
	}

}

Create new folder named views in src\main\webapp\WEB-INF folder. In views folder, create new folder named product. In product folder, create new JSP file named index.jsp as below:

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
	pageEncoding="ISO-8859-1"%>
<%@ taglib prefix="s" uri="/struts-tags"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Spring and Struts 2 Integration</title>
</head>
<body>

	<h3>Product List</h3>
	<s:form method="get" namespace="/product" action="search">
		<s:textfield label="Keyword" name="keyword"></s:textfield>
		<s:submit value="Search" align="left"></s:submit>
	</s:form>
	<table border="1">
		<tr>
			<th>Id</th>
			<th>Name</th>
			<th>Price</th>
			<th>Quantity</th>
			<th>Status</th>
			<th>Description</th>
		</tr>
		<c:forEach var="product" items="${products }">
			<tr>
				<td>${product.id }</td>
				<td>${product.name }</td>
				<td>${product.price }</td>
				<td>${product.quantity }</td>
				<td>${product.status }</td>
				<td>${product.description }</td>
			</tr>
		</c:forEach>
	</table>

</body>
</html>




Create new jsp file named index.jsp in src\main\webapp folder as below:

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<jsp:forward page="product/index.html"></jsp:forward>

Select project, right click and select Run on Server menu

Access index method in product action with following url:

http://localhost:8080/LearnStrutsFrameworkWithRealApps/product/index.html

Output

Search with bile keyword

Search with top keyword