1. Overview
In this tutorial, We'll learn how to create a simple ToDo web application using the Spring web framework. Spring web framework is called as officially Spring MVC. Let us create a simple REST api with CRUD operations such as Create, Read, Update, and Delete. You will learn and understand by a step by step tutorial. In the previous article, we have shown how to build a first Hello World application in Spring Boot and all possible real-time exceptions.
Spring 5.0.3.RELEASE
Bootstrap 3.3.7
Hibernate 4.3.11.Final
h2.version 1.4.197
JDK 1.8
Spring data 1.11.4.RELEASE
2. Create a Maven Web Application
First, We have to create a simple web application using maven command.
mvn archetype:generate -DgroupId=com.javaprogramto.todo -DartifactId=todo -Dversion=0.0.1-SNAPSHOT -DinteractiveMode=false -DarchetypeArtifactId=maven-archetype-webapp
This command generates a very basic web application structure. Under folder src/main only two directories will be created such as resources and webapp.
Folder java will not be created. You need to create it manually.
Note: After executing this command, you must see the pom.xml file in the project root folder.
3. Adding dependencies to pom.xml
Let us add all the dependencies that are required for this project.
<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>com.javaprogramto.todo</groupId> <artifactId>todo</artifactId> <packaging>war</packaging> <version>0.0.1-SNAPSHOT</version> <name>todo Webapp</name> <properties> <!-- Generic properties --> <java.version>1.8</java.version> <!-- Web --> <jsp.version>2.2</jsp.version> <jstl.version>1.2</jstl.version> <servlet.version>3.1.0</servlet.version> <bootstrap.version>3.3.7</bootstrap.version> <jackson.version>2.9.2</jackson.version> <webjars.version>0.32</webjars.version> <!-- Spring --> <spring-framework.version> 5.0.3.RELEASE </spring-framework.version> <!-- JPA --> <spring-data-jpa>1.11.4.RELEASE</spring-data-jpa> <hibernate-jpa.version>1.0.0.Final</hibernate-jpa.version> <hibernate.version>4.3.11.Final</hibernate.version> <!-- Drivers --> <h2.version>1.4.197</h2.version> <!-- Logs --> <slf4j.version>1.7.25</slf4j.version> <logback.version>1.2.3</logback.version> </properties> <dependencies> <!-- Spring MVC --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>${spring-framework.version}</version> </dependency> <!-- Spring Data JPA --> <dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-jpa</artifactId> <version>${spring-data-jpa}</version> </dependency> <dependency> <groupId>org.hibernate.javax.persistence</groupId> <artifactId>hibernate-jpa-2.1-api</artifactId> <version>${hibernate-jpa.version}</version> </dependency> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-core</artifactId> <version>${hibernate.version}</version> </dependency> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-entitymanager</artifactId> <version>${hibernate.version}</version> </dependency> <!-- Logs --> <dependency> <groupId>org.slf4j</groupId> <artifactId>jcl-over-slf4j</artifactId> <version>${slf4j.version}</version> </dependency> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> <version>${logback.version}</version> </dependency> <!-- Drivers --> <dependency> <groupId>com.h2database</groupId> <artifactId>h2</artifactId> <version>${h2.version}</version> <scope>runtime</scope> </dependency> <!-- Java EE Web dependencies --> <dependency> <groupId>javax.servlet</groupId> <artifactId>jstl</artifactId> <version>${jstl.version}</version> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>${servlet.version}</version> <scope>provided</scope> </dependency> <dependency> <groupId>javax.servlet.jsp</groupId> <artifactId>jsp-api</artifactId> <version>${jsp.version}</version> <scope>provided</scope> </dependency> <!-- Web UI --> <dependency> <groupId>org.webjars</groupId> <artifactId>webjars-locator</artifactId> <version>${webjars.version}</version> </dependency> <dependency> <groupId>org.webjars</groupId> <artifactId>bootstrap</artifactId> <version>${bootstrap.version}</version> </dependency> <!-- Web - JSON/XML Response --> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>${jackson.version}</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.datatype</groupId> <artifactId>jackson-datatype-joda</artifactId> <version>${jackson.version}</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.dataformat</groupId> <artifactId>jackson-dataformat-xml</artifactId> <version>${jackson.version}</version> </dependency> </dependencies> <build> <finalName>todo</finalName> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>1.8</source> <target>1.8</target> </configuration> </plugin> </plugins> </build> </project>
4. Web.xml Configuration
Adding DispatcherServlet in web.xml and this is the main entry point for this web app that acts as front controller to handles all incoming requests.
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5"> <display-name>ToDo Web Application</display-name> <servlet> <servlet-name>todoDispatcherServlet</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>todoDispatcherServlet</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> </web-app>
5. Spring Configuration File
Spring DispatcherServlet will look for the configuration file with the name "todoDispatcherServlet-servlet.xml" in the WEB-INF folder. This name is a combination of "servlet-name" and '-servlet'.
Configure the following beans which are needed for rest and web application.
todoDispatcherServlet-servlet.xml:
<context:component-scan base-package="com.javaprogramto.todo" /> <mvc:annotation-driven> <mvc:message-converters> <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"> <property name="objectMapper" ref="jsonMapper" /> </bean> <bean class="org.springframework.http.converter.xml.MappingJackson2XmlHttpMessageConverter"> <property name="objectMapper" ref="xmlMapper" /> </bean> </mvc:message-converters> </mvc:annotation-driven> <bean id="jsonMapper" class="org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean"> <property name="simpleDateFormat" value="yyyy-MM-dd HH:mm:ss" /> </bean> <bean id="xmlMapper" parent="jsonMapper"> <property name="createXmlMapper" value="true" /> </bean> <mvc:resources mapping="/webjars/**" location="classpath:META-INF/resources/webjars/" /> <jpa:repositories base-package="com.javaprogramto.todo.repository" /> <jdbc:embedded-database id="dataSource" type="H2"> <jdbc:script location="classpath:META-INF/sql/schema.sql" /> <jdbc:script location="classpath:META-INF/sql/data.sql" /> </jdbc:embedded-database> <bean id="jpaVendorAdapter" class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"> <property name="showSql" value="true" /> </bean> <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> <property name="dataSource" ref="dataSource" /> <property name="jpaVendorAdapter" ref="jpaVendorAdapter" /> </bean> <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"> <property name="entityManagerFactory" ref="entityManagerFactory" /> </bean> <tx:annotation-driven transaction-manager="transactionManager" /> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/views/" /> <property name="suffix" value=".jsp" /> </bean> <bean id="h2WebServer" class="org.h2.tools.Server" factory-method="createWebServer" init-method="start" destroy-method="stop"> <constructor-arg value="-web,-webAllowOthers,-webDaemon,-webPort,8082" /> </bean>
<context:component-scan/> is to detect the all classes that annotated with @Configuration and @Service.
<mvc:annotation-driven/> is to detect the classes with @Controller and @RESTController.
<jpa:repositories/> is to find the interfaces that extends CrudRepository interfaces
6. SQL Scripts and JPA Repository - Persistance Unit
We are going to use table creation and data insertion scripts in our example.
6.1 schema.sql:
create table todo ( id varchar(36) not null, description varchar(255) not null, created timestamp, modified timestamp, completed boolean, primary key (id) );
6.2 data.sql
insert into todo values ('7fd921cfd2b64dc7b995633e8209f386','Pay House Rent','2019-09-23 15:00:01','2019-09-23 15:00:01',false);
insert into todo values ('5820a4c2abe74f409da89217bf905a0s','Study Documents','2019-09-02 16:00:01','2019-09-02 16:00:01',false);
insert into todo values ('a44b6db26aef49e39d1b68622f55c34j','Doctor Consultation','2019-09-18 12:00:00','2019-09-18 12:00:00',false);
6.3 /resources/META-INF/persistence.xml
Create a persistence unit in the persistence.xml file as below.
<?xml version="1.0" encoding="UTF-8" ?> <persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd" version="1.0"> <persistence-unit name="toDo"> <description>My Persistence Unit</description> </persistence-unit> </persistence>
Spring DAO Library will handle all the required dependencies for connection and its mapping classes. We need to just declare only <persistence-unit> name.
Note: Once you complete all these configurations, please run "maven install" project in eclipse or through the command line.
Do maven -> "update project" to update the dependencies for this project.
7. Create ToDo Application classes
As of now, we have seen all the configurations required for this app. Let us create java classes.
7.1 ToDo Entity Class
This class interacts and maps to the actual database table "todo".
package com.javaprogramto.todo.domain; import java.sql.Timestamp; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; import org.hibernate.annotations.GenericGenerator; @Entity public class ToDo { @Id @GeneratedValue(generator = "system-uuid") @GenericGenerator(name = "system-uuid", strategy = "uuid") private String id; private String description; private Timestamp created; private Timestamp modified; private boolean completed; public ToDo() { } public String getId() { return id; } public void setId(String id) { this.id = id; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } public Timestamp getCreated() { return created; } public void setCreated(Timestamp created) { this.created = created; } public Timestamp getModified() { return modified; } public void setModified(Timestamp modified) { this.modified = modified; } public boolean isCompleted() { return completed; } }
@Entity is to tell spring DAO that this is the mapping to the table.
@Id is to indicate this property as Primary Key
@GeneratedValue(generator = "system-uuid") is to generate 36 character random guid code.
7.2 Creating Repository
Create an interface that extends the CrudRepository interface which takes Entity class and primary key Id type. In our case, entity class is ToDo and the primary key type is String.
package com.javaprogramto.todo.repository; import org.springframework.data.repository.CrudRepository; import com.javaprogramto.todo.domain.ToDo; public interface ToDoRepository extends CrudRepository<ToDo, String> { }
This class is scanned and identified by <jpa:repositories/> tag in todoDispatcherServlet-servlet.xml file. Because this tag is pointing to package "com.javaprogramto.todo.repository".
7.3 Creating Controller Class
This class is annotated with @Controller which is indentified by <mv:annotation-driven/> tag. Maps @GetMapping, @RequestMapping, and @PostMapping annotations to accept requests for paths / and /toDos.
This controller class needs a ToDoRepository so it should be wired up properly. Spring provides another annotation @Autowired which does wiring up the dependency by spring framework. Dependency is injected by the spring container.
package com.javaprogramto.todo.controller; import javax.servlet.http.HttpServletRequest; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestHeader; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.servlet.ModelAndView; import com.javaprogramto.todo.domain.ToDo; import com.javaprogramto.todo.repository.ToDoRepository; @Controller @RequestMapping("/") public class ToDoController { private ToDoRepository repository; @Autowired public ToDoController(ToDoRepository repository) { this.repository = repository; } @GetMapping public ModelAndView index(ModelAndView modelAndView, HttpServletRequest request) { modelAndView.setViewName("index"); return modelAndView; } @RequestMapping(value = "/toDos", method = { RequestMethod.GET }, produces = { MediaType.APPLICATION_JSON_UTF8_VALUE, MediaType.APPLICATION_XML_VALUE, MediaType.TEXT_XML_VALUE }) public ResponseEntity<Iterable<ToDo>> getToDos(@RequestHeader HttpHeaders headers) { return new ResponseEntity<Iterable<ToDo>>(this.repository.findAll(), headers, HttpStatus.OK); } }
GetMapping request to path "/" will bring the index.jsp page.
GetMapping request to path "/toDos" will fetch all ToDo records from the database using the repository.findAll() method and returns the response as JSON.
7.4 Home page index.jsp file
Let us create a simple home page when URL "/" is hit.
src/main/webapp/WEB-INF/views/index.jsp
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> <!doctype html> <html> <head> <meta charset="UTF-8"> <title>Simple Directory Web App</title> <link rel="stylesheet" type="text/css" href="webjars/bootstrap/3.3.7/css/bootstrap.min.css"> <link rel="stylesheet" type="text/css" href="webjars/bootstrap/3.3.7/css/bootstrap-theme.min.css"> </head> <body> <div class="container theme-showcase" role="main"> <div class="jumbotron"> <h1>ToDo Application</h1> <p>A simple Rest API Spring MVC application</p> </div> <div class="page-header"> <h1>API</h1> <a href="toDos">Current ToDos</a> </div> </div> </body> </html>
In this jsp file, we have mentioned bootstrap.min.css. You might have a question and where it is coming from?
We have already declared webjars:bootstrap dependency in pom.xml and <mvc:resources/> tag in dispatcherServlet-servlet.xml file. These two will make bootstrap library files available to this application.
8. Build and Deploy the app in Tomcat Server
Let us build the app using the maven install command which generates the todo-0.0.1-SNAPSHOT.war file.
Copy the generated war file into tomcat/webapps folder. Next, run the startup.bat for windows and startup.sh for UNIX/mac.
Hit http://localhost:8080/todo/ from your favorite browser. This will display the index.jsp file.
localhost:8080/todo/toDos
This request will be sent to the toDos mapping in the controller and fetches all three records from DB and shows on the browser.
<ArrayList> <item> <id>7fd921cfd2b64dc7b995633e8209f386</id> <description>Pay House Rent</description> <created>2019-09-23 15:00:01</created> <modified>2019-09-23 15:00:01</modified> <completed>false</completed> </item> <item> <id>5820a4c2abe74f409da89217bf905a0s</id> <description>Study Documents</description> <created>2019-09-02 16:00:01</created> <modified>2019-09-02 16:00:01</modified> <completed>false</completed> </item> <item> <id>a44b6db26aef49e39d1b68622f55c34j</id> <description>Doctor Consultation</description> <created>2019-09-18 12:00:00</created> <modified>2019-09-18 12:00:00</modified> <completed>false</completed> </item> </ArrayList>
The response can be viewed in json using the curl command.
curl -H "Accept: application/json" localhost:8080/todo/toDos
9. Using App Config
Some of the developers may think using XML configuration is verbose and not convenient. We can configure in another way using annotations and java-config classes.
All the tags inside todoDispatcherServlet-servlet.xml can be moved to java file as below.
package com.javaprogramto.todo.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.jpa.repository.config.EnableJpaRepositories; import org.springframework.http.converter.HttpMessageConverter; import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder; import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; import org.springframework.http.converter.xml.MappingJackson2XmlHttpMessageConverter; import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType; import org.springframework.orm.jpa.JpaTransactionManager; 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 org.springframework.web.servlet.config.annotation.EnableWebMvc; import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import org.springframework.web.servlet.resource.WebJarsResourceResolver; import org.springframework.web.servlet.view.InternalResourceViewResolver; import javax.sql.DataSource; import java.text.SimpleDateFormat; import java.util.List; @Configuration @EnableJpaRepositories(basePackages = "com.apress.todo.repository") @EnableTransactionManagement @EnableWebMvc public class ToDoConfig implements WebMvcConfigurer { @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler("/webjars/**") .addResourceLocations("classpath:/META-INF/resources/webjars/", "/resources/", "/webjars/") .resourceChain(true).addResolver(new WebJarsResourceResolver()); } @Override public void configureMessageConverters(List<HttpMessageConverter<?>> converters) { Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder(); builder.indentOutput(true).dateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")); converters.add(new MappingJackson2HttpMessageConverter(builder.build())); converters.add(new MappingJackson2XmlHttpMessageConverter(builder.createXmlMapper(true).build())); } @Bean public InternalResourceViewResolver jspViewResolver() { InternalResourceViewResolver bean = new InternalResourceViewResolver(); bean.setPrefix("/WEB-INF/views/"); bean.setSuffix(".jsp"); return bean; } @Bean public DataSource dataSource() { EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder(); return builder.setType(EmbeddedDatabaseType.H2).addScript("META-INF/sql/schema.sql") .addScript("META-INF/sql/data.sql").build(); } public LocalContainerEntityManagerFactoryBean entityManagerFactory() { HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter(); vendorAdapter.setShowSql(true); LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean(); factory.setJpaVendorAdapter(vendorAdapter); factory.setDataSource(dataSource()); return factory; } @Bean public PlatformTransactionManager transactionManager() { JpaTransactionManager txManager = new JpaTransactionManager(); txManager.setEntityManagerFactory(entityManagerFactory().getNativeEntityManagerFactory()); return txManager; } }
<context:component-scan base-package="com.apress.todo" />
10. Spring Exceptions and Solutions
The following exceptions have occurred during the development of this ToDo application.
10.1 Verify the dependency is in pom.xml file:
dependency name: spring-webmvc
Jan 06, 2020 3:41:19 PM org.apache.catalina.core.StandardContext loadOnStartup
SEVERE: Servlet [todoDispatcherServlet] in web application [/todo] threw load() exception
java.lang.ClassNotFoundException: org.springframework.web.servlet.DispatcherServlet
at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1365)
at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1188)
at org.apache.catalina.core.DefaultInstanceManager.loadClass(DefaultInstanceManager.java:540)
at org.apache.catalina.core.DefaultInstanceManager.loadClassMaybePrivileged(DefaultInstanceManager.java:521)
at org.apache.catalina.core.DefaultInstanceManager.newInstance(DefaultInstanceManager.java:150)
at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1042)
at org.apache.catalina.core.StandardWrapper.load(StandardWrapper.java:983)
at org.apache.catalina.core.StandardContext.loadOnStartup(StandardContext.java:4871)
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5180)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1384)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1374)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at org.apache.tomcat.util.threads.InlineExecutorService.execute(InlineExecutorService.java:75)
at java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:134)
at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:909)
at org.apache.catalina.core.StandardHost.startInternal(StandardHost.java:841)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1384)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1374)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at org.apache.tomcat.util.threads.InlineExecutorService.execute(InlineExecutorService.java:75)
at java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:134)
at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:909)
at org.apache.catalina.core.StandardEngine.startInternal(StandardEngine.java:262)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
at org.apache.catalina.core.StandardService.startInternal(StandardService.java:421)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
at org.apache.catalina.core.StandardServer.startInternal(StandardServer.java:930)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
at org.apache.catalina.startup.Catalina.start(Catalina.java:633)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:343)
at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:474)
10.2 If servlet name and mappings are not in matching:
SEVERE: A child container failed during start
java.util.concurrent.ExecutionException: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Catalina].StandardHost[localhost].StandardContext[/todo]]
at java.util.concurrent.FutureTask.report(FutureTask.java:122)
at java.util.concurrent.FutureTask.get(FutureTask.java:192)
at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:916)
at org.apache.catalina.core.StandardHost.startInternal(StandardHost.java:841)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1384)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1374)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at org.apache.tomcat.util.threads.InlineExecutorService.execute(InlineExecutorService.java:75)
at java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:134)
at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:909)
at org.apache.catalina.core.StandardEngine.startInternal(StandardEngine.java:262)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
at org.apache.catalina.core.StandardService.startInternal(StandardService.java:421)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
at org.apache.catalina.core.StandardServer.startInternal(StandardServer.java:930)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
at org.apache.catalina.startup.Catalina.start(Catalina.java:633)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:343)
at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:474)
Caused by: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Catalina].StandardHost[localhost].StandardContext[/todo]]
at org.apache.catalina.util.LifecycleBase.handleSubClassException(LifecycleBase.java:440)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:198)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1384)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1374)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at org.apache.tomcat.util.threads.InlineExecutorService.execute(InlineExecutorService.java:75)
at java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:134)
at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:909)
... 21 more
Caused by: java.lang.IllegalArgumentException: Servlet mapping specifies an unknown servlet name [dispatcherServlet]
at org.apache.catalina.core.StandardContext.addServletMappingDecoded(StandardContext.java:3174)
at org.apache.catalina.Context.addServletMappingDecoded(Context.java:881)
at org.apache.catalina.startup.ContextConfig.configureContext(ContextConfig.java:1391)
at org.apache.catalina.startup.ContextConfig.webConfig(ContextConfig.java:1168)
at org.apache.catalina.startup.ContextConfig.configureStart(ContextConfig.java:774)
at org.apache.catalina.startup.ContextConfig.lifecycleEvent(ContextConfig.java:301)
at org.apache.catalina.util.LifecycleBase.fireLifecycleEvent(LifecycleBase.java:123)
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5051)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
... 27 more
Jan 06, 2020 3:36:57 PM org.apache.catalina.core.ContainerBase startInternal
SEVERE: A child container failed during start
java.util.concurrent.ExecutionException: org.apache.catalina.LifecycleException: A child container failed during start
at java.util.concurrent.FutureTask.report(FutureTask.java:122)
at java.util.concurrent.FutureTask.get(FutureTask.java:192)
at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:916)
at org.apache.catalina.core.StandardEngine.startInternal(StandardEngine.java:262)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
at org.apache.catalina.core.StandardService.startInternal(StandardService.java:421)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
at org.apache.catalina.core.StandardServer.startInternal(StandardServer.java:930)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
at org.apache.catalina.startup.Catalina.start(Catalina.java:633)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:343)
at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:474)
Caused by: org.apache.catalina.LifecycleException: A child container failed during start
at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:928)
at org.apache.catalina.core.StandardHost.startInternal(StandardHost.java:841)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1384)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1374)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at org.apache.tomcat.util.threads.InlineExecutorService.execute(InlineExecutorService.java:75)
at java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:134)
at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:909)
... 13 more
Caused by: java.util.concurrent.ExecutionException: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Catalina].StandardHost[localhost].StandardContext[/todo]]
at java.util.concurrent.FutureTask.report(FutureTask.java:122)
at java.util.concurrent.FutureTask.get(FutureTask.java:192)
at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:916)
... 21 more
Caused by: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Catalina].StandardHost[localhost].StandardContext[/todo]]
at org.apache.catalina.util.LifecycleBase.handleSubClassException(LifecycleBase.java:440)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:198)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1384)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1374)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at org.apache.tomcat.util.threads.InlineExecutorService.execute(InlineExecutorService.java:75)
at java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:134)
at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:909)
... 21 more
Caused by: java.lang.IllegalArgumentException: Servlet mapping specifies an unknown servlet name [dispatcherServlet]
at org.apache.catalina.core.StandardContext.addServletMappingDecoded(StandardContext.java:3174)
at org.apache.catalina.Context.addServletMappingDecoded(Context.java:881)
at org.apache.catalina.startup.ContextConfig.configureContext(ContextConfig.java:1391)
at org.apache.catalina.startup.ContextConfig.webConfig(ContextConfig.java:1168)
at org.apache.catalina.startup.ContextConfig.configureStart(ContextConfig.java:774)
at org.apache.catalina.startup.ContextConfig.lifecycleEvent(ContextConfig.java:301)
at org.apache.catalina.util.LifecycleBase.fireLifecycleEvent(LifecycleBase.java:123)
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5051)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
... 27 more
Jan 06, 2020 3:36:57 PM org.apache.catalina.startup.Catalina start
SEVERE: The required Server component failed to start so Tomcat is unable to start.
org.apache.catalina.LifecycleException: A child container failed during start
at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:928)
at org.apache.catalina.core.StandardEngine.startInternal(StandardEngine.java:262)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
at org.apache.catalina.core.StandardService.startInternal(StandardService.java:421)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
at org.apache.catalina.core.StandardServer.startInternal(StandardServer.java:930)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
at org.apache.catalina.startup.Catalina.start(Catalina.java:633)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:343)
at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:474)
Caused by: java.util.concurrent.ExecutionException: org.apache.catalina.LifecycleException: A child container failed during start
at java.util.concurrent.FutureTask.report(FutureTask.java:122)
at java.util.concurrent.FutureTask.get(FutureTask.java:192)
at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:916)
... 13 more
Caused by: org.apache.catalina.LifecycleException: A child container failed during start
at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:928)
at org.apache.catalina.core.StandardHost.startInternal(StandardHost.java:841)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1384)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1374)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at org.apache.tomcat.util.threads.InlineExecutorService.execute(InlineExecutorService.java:75)
at java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:134)
at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:909)
... 13 more
Caused by: java.util.concurrent.ExecutionException: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Catalina].StandardHost[localhost].StandardContext[/todo]]
at java.util.concurrent.FutureTask.report(FutureTask.java:122)
at java.util.concurrent.FutureTask.get(FutureTask.java:192)
at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:916)
... 21 more
Caused by: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Catalina].StandardHost[localhost].StandardContext[/todo]]
at org.apache.catalina.util.LifecycleBase.handleSubClassException(LifecycleBase.java:440)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:198)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1384)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1374)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at org.apache.tomcat.util.threads.InlineExecutorService.execute(InlineExecutorService.java:75)
at java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:134)
at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:909)
... 21 more
Caused by: java.lang.IllegalArgumentException: Servlet mapping specifies an unknown servlet name [dispatcherServlet]
at org.apache.catalina.core.StandardContext.addServletMappingDecoded(StandardContext.java:3174)
at org.apache.catalina.Context.addServletMappingDecoded(Context.java:881)
at org.apache.catalina.startup.ContextConfig.configureContext(ContextConfig.java:1391)
at org.apache.catalina.startup.ContextConfig.webConfig(ContextConfig.java:1168)
at org.apache.catalina.startup.ContextConfig.configureStart(ContextConfig.java:774)
at org.apache.catalina.startup.ContextConfig.lifecycleEvent(ContextConfig.java:301)
at org.apache.catalina.util.LifecycleBase.fireLifecycleEvent(LifecycleBase.java:123)
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5051)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
... 27 more
Jan 06, 2020 3:36:57 PM org.apache.coyote.AbstractProtocol pause
INFO: Pausing ProtocolHandler ["http-nio-8080"]
Jan 06, 2020 3:36:57 PM org.apache.coyote.AbstractProtocol pause
INFO: Pausing ProtocolHandler ["ajp-nio-8009"]
Jan 06, 2020 3:36:57 PM org.apache.catalina.core.StandardService stopInternal
INFO: Stopping service [Catalina]
Jan 06, 2020 3:36:57 PM org.apache.coyote.AbstractProtocol destroy
INFO: Destroying ProtocolHandler ["http-nio-8080"]
Jan 06, 2020 3:36:57 PM org.apache.coyote.AbstractProtocol destroy
INFO: Destroying ProtocolHandler ["ajp-nio-8009"]
10.3 If persistence.xml file is missing:
2020-01-06 16:05:05 ERROR o.s.web.servlet.DispatcherServlet - Context initialization failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in ServletContext resource [/WEB-INF/todoDispatcherServlet-servlet.xml]: Invocation of init method failed; nested exception is java.lang.IllegalStateException: No persistence units parsed from {classpath*:META-INF/persistence.xml}
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1710)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:583)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:502)
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:312)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:310)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200)
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1085)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:858)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:549)
at org.springframework.web.servlet.FrameworkServlet.configureAndRefreshWebApplicationContext(FrameworkServlet.java:676)
at org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:642)
at org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:690)
at org.springframework.web.servlet.FrameworkServlet.initWebApplicationContext(FrameworkServlet.java:558)
at org.springframework.web.servlet.FrameworkServlet.initServletBean(FrameworkServlet.java:499)
at org.springframework.web.servlet.HttpServletBean.init(HttpServletBean.java:172)
at javax.servlet.GenericServlet.init(GenericServlet.java:158)
at org.apache.catalina.core.StandardWrapper.initServlet(StandardWrapper.java:1134)
at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1089)
at org.apache.catalina.core.StandardWrapper.load(StandardWrapper.java:983)
at org.apache.catalina.core.StandardContext.loadOnStartup(StandardContext.java:4871)
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5180)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:717)
at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:690)
at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:705)
at org.apache.catalina.startup.HostConfig.deployWAR(HostConfig.java:978)
at org.apache.catalina.startup.HostConfig$DeployWar.run(HostConfig.java:1849)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at org.apache.tomcat.util.threads.InlineExecutorService.execute(InlineExecutorService.java:75)
at java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:112)
at org.apache.catalina.startup.HostConfig.deployWARs(HostConfig.java:773)
at org.apache.catalina.startup.HostConfig.deployApps(HostConfig.java:427)
at org.apache.catalina.startup.HostConfig.start(HostConfig.java:1576)
at org.apache.catalina.startup.HostConfig.lifecycleEvent(HostConfig.java:309)
at org.apache.catalina.util.LifecycleBase.fireLifecycleEvent(LifecycleBase.java:123)
at org.apache.catalina.util.LifecycleBase.setStateInternal(LifecycleBase.java:423)
at org.apache.catalina.util.LifecycleBase.setState(LifecycleBase.java:366)
at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:936)
at org.apache.catalina.core.StandardHost.startInternal(StandardHost.java:841)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1384)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1374)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at org.apache.tomcat.util.threads.InlineExecutorService.execute(InlineExecutorService.java:75)
at java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:134)
at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:909)
at org.apache.catalina.core.StandardEngine.startInternal(StandardEngine.java:262)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
at org.apache.catalina.core.StandardService.startInternal(StandardService.java:421)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
at org.apache.catalina.core.StandardServer.startInternal(StandardServer.java:930)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
at org.apache.catalina.startup.Catalina.start(Catalina.java:633)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:343)
at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:474)
Caused by: java.lang.IllegalStateException: No persistence units parsed from {classpath*:META-INF/persistence.xml}
at org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager.obtainDefaultPersistenceUnitInfo(DefaultPersistenceUnitManager.java:680)
at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.determinePersistenceUnitInfo(LocalContainerEntityManagerFactoryBean.java:375)
at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:329)
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:370)
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:359)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1769)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1706)
... 60 common frames omitted
11. Conclusion
In this article, We've seen how to build a ToDo application in Spring. And also shown replacing all XML configurations with java config classes and annotations.
Finally, showcased the errors found during the development of this app.
In the next article, we will build the same ToDo web application with Spring Boot.
No comments:
Post a Comment
Please do not add any spam links in the comments section.