Monday, October 31, 2016

Create an easy Servlet

Today I will try to create an asy servlet to run at my server. To encapsulate buisness logic (how my fields and variables will interact with each other) I will use CDI beans. We will (use EJB to) manually control transactions and JSF to display view.

Our program is to manage cats in cat shelter where we should add the cat if we found one, delete one from the list if it found it's house and to see the full list of cats in the shelter if somebody wants to choose one.

Every cat is going to be entity for us and this entity we want to store in the relational database and to map entity there we're using JPA. It is the popular API for the management of persistence and object/relationalmapping with Java EE, we will stay with it.

Before we started, here is working code you can download and try. If you have any problems feel free to ask in comments.
Let's see what we need in pom.xml (which we place in the root directory of our project):
1:  <?xml version="1.0" encoding="UTF-8"?> <!-- standalone="no"?> -->  
2:  <project xmlns="http://maven.apache.org/POM/4.0.0"  
3:       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
4:       xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">  
5:    <modelVersion>4.0.0</modelVersion>  
6:    <groupId>catchelter</groupId>  
7:    <artifactId>catshelter-java</artifactId>  
8:    <version>1.0-SNAPSHOT</version>  
9:    <packaging>war</packaging>  
10:    <properties>  
11:      <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>  
12:      <version.wildfly.maven.plugin>1.0.2.Final</version.wildfly.maven.plugin>  
13:      <version.jboss.spec.javaee.7.0>1.0.3.Final</version.jboss.spec.javaee.7.0>  
14:      <version.war.plugin>3.0.0</version.war.plugin>  
15:      <maven.compiler.target>1.8</maven.compiler.target>  
16:      <maven.compiler.source>1.8</maven.compiler.source>  
17:    </properties>  
18:    <dependencyManagement>  
19:      <dependencies>  
20:        <!-- JBoss version  
21:           JavaEE 7  
22:           Any d-s from org.jboss.spec-->  
23:        <dependency>  
24:          <groupId>org.jboss.spec</groupId>  
25:          <artifactId>jboss-javaee-7.0</artifactId>  
26:          <version>${version.jboss.spec.javaee.7.0}</version>  
27:          <type>pom</type>  
28:          <scope>import</scope>  
29:        </dependency>  
30:      </dependencies>  
31:    </dependencyManagement>  
32:    <dependencies>  
33:      <!-- CDI API Context and Dependency injection-->  
34:      <dependency>  
35:        <groupId>javax.enterprise</groupId>  
36:        <artifactId>cdi-api</artifactId>  
37:        <scope>provided</scope>  
38:      </dependency>  
39:      <!-- Common annotation API (JRS-250)-->  
40:      <dependency>  
41:        <groupId>org.jboss.spec.javax.annotation</groupId>  
42:        <artifactId>jboss-annotations-api_1.2_spec</artifactId>  
43:        <scope>provided</scope>  
44:      </dependency>  
45:      <!-- JSF API Java Server Faces-->  
46:      <dependency>  
47:        <groupId>org.jboss.spec.javax.faces</groupId>  
48:        <artifactId>jboss-jsf-api_2.2_spec</artifactId>  
49:        <scope>provided</scope>  
50:      </dependency>  
51:      <!-- JTA - transaction api-->  
52:      <!-- JPA Java Persistence api-->  
53:      <dependency>  
54:        <groupId>org.hibernate.javax.persistence</groupId>  
55:        <artifactId>hibernate-jpa-2.1-api</artifactId>  
56:        <scope>provided</scope>  
57:      </dependency>  
58:      <!--JPA -->  
59:      <dependency>  
60:        <groupId>org.jboss.spec.javax.transaction</groupId>  
61:        <artifactId>jboss-transaction-api_1.2_spec</artifactId>  
62:        <scope>provided</scope>  
63:      </dependency>  
64:      <!--EJB API-->  
65:      <dependency>  
66:        <groupId>org.jboss.spec.javax.ejb</groupId>  
67:        <artifactId>jboss-ejb-api_3.2_spec</artifactId>  
68:        <scope>provided</scope>  
69:      </dependency>  
70:    </dependencies>  
71:    <build>  
72:      <finalName>${project.artifactId}</finalName>  
73:      <plugins>  
74:        <plugin>  
75:          <artifactId>maven-war-plugin</artifactId>  
76:          <version>${version.war.plugin}</version>  
77:          <configuration>  
78:            <failOnMissingWebXml>false</failOnMissingWebXml>  
79:          </configuration>  
80:        </plugin>  
81:        <plugin>  
82:          <groupId>org.wildfly.plugins</groupId>  
83:          <artifactId>wildfly-maven-plugin</artifactId>  
84:          <version>${version.wildfly.maven.plugin}</version>  
85:          <configuration>  
86:            <hostname>${wildfly-hostname}</hostname>  
87:            <port>9991</port>  
88:            <username>${wildfly-username}</username>  
89:            <password>${wildfly-password}</password>  
90:          </configuration>  
91:        </plugin>  
92:      </plugins>  
93:    </build>  
94:  </project>  
Note we configured wildfly-maven-plugin with our local configuration, as said in previous post.

To include CDI and JSF to our project we need to add empty bean beans.xml to directory %PROJECT%/src/main/webapp to make wildfly look for beans in this application and accept the CDI.
1:  <?xml version="1.0" encoding="UTF-8"?>  
2:  <beans  
3:      xmlns="http://xmlns.jcp.org/xml/ns/javaee"  
4:      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
5:      xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee   
6:             http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd"  
7:      bean-discovery-mode="all">  
8:  </beans>  

Also we have faces-config.xml in the same place, we use a standardized version JSF-2.0, that's why we leave default configurations.
1:  <?xml version='1.0' encoding='UTF-8'?>  
2:  <faces-config version="2.2" xmlns="http://xmlns.jcp.org/xml/ns/javaee"  
3:    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
4:    xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee   
5:    http://xmlns.jcp.org/xml/ns/javaee/web-facesconfig_2_2.xsd">  
6:  </faces-config>  

What is very nice - we can add all the default configurations of beans.xml and faces-config.xml by one click if we use Intellij IDE? which I really like.
  
Same folder we will add web.xml where we configure start page where we will display the information.
1:  <?xml version="1.0" encoding="UTF-8"?>  
2:  <web-app version="3.1"  
3:       xmlns="http://xmlns.jcp.org/xml/ns/javaee"  
4:       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
5:       xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd">  
6:    <servlet>  
7:      <servlet-name>Faces Servlet</servlet-name>  
8:      <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>  
9:      <load-on-startup>1</load-on-startup>  
10:    </servlet>  
11:    <servlet-mapping>  
12:      <servlet-name>Faces Servlet</servlet-name>  
13:      <url-pattern>*.xhtml</url-pattern>  
14:    </servlet-mapping>  
15:    <session-config>  
16:      <session-timeout>  
17:        30  
18:      </session-timeout>  
19:    </session-config>  
20:    <welcome-file-list>  
21:      <welcome-file>main.xhtml</welcome-file>  
22:    </welcome-file-list>  
23:  </web-app>  

Each cat will be an Entity, for it we create an Entity class in %PROGECT%/main/java/org/jboss/cats/domain


1:  package org.jboss.cats.domain;  
2:  import javax.persistence.Column;  
3:  import javax.persistence.Entity;  
4:  import javax.persistence.GeneratedValue;  
5:  import javax.persistence.Id;  
6:  import javax.persistence.Table;  
7:  /**  
8:   * Created by Anna Leonenko on 30/10/2016.  
9:   */  
10:  @Entity  
11:  @Table(name = "Users")  
12:  public class Cat {  
13:    @Id  
14:    @GeneratedValue  
15:    private Long id;  
16:    @Column(unique = true)  
17:    private String name;  
18:    private String color;  
19:    private int age;  
20:    private String fluffy;  
21:    public String isFluffy() {  
22:      return fluffy;  
23:    }  
24:    public int getAge() {  
25:      return age;  
26:    }  
27:    public Long getId() {  
28:      return id;  
29:    }  
30:    public String getColor() {  
31:      return color;  
32:    }  
33:    public String getName() {  
34:      return name;  
35:    }  
36:    public void setAge(int age) {  
37:      this.age = age;  
38:    }  
39:    public void setColor(String color) {  
40:      this.color = color;  
41:    }  
42:    public void setFluffy(String fluffy) {  
43:      this.fluffy = fluffy;  
44:    }  
45:    public void setName(String name) {  
46:      this.name = name;  
47:    }  
48:  }  
We wired the Table "Cats" there by special annotation, set primary key which is String name here and set generated value id.

Then we create a class to manage our datasource (let's use ExampleDS database for now).
First declare the interface at %PROGECT%/main/java/org/jboss/cats/domain:
1:  package org.jboss.cats.domain;  
2:  public interface CatDao {  
3:    Cat getForName(String name);  
4:    void addCat(Cat cat);  
5:  }  

Then, implement it in same folder:
1:  package org.jboss.cats.domain;  
2:  import javax.inject.Inject;  
3:  import javax.persistence.EntityManager;  
4:  import javax.transaction.SystemException;  
5:  import javax.transaction.UserTransaction;  
6:  public class ManagedBeanCatDao implements CatDao {  
7:    @Inject  
8:    private EntityManager entityManager;  
9:    @Inject  
10:    UserTransaction utx;  
11:    @Override  
12:    public Cat getForName(String name) {  
13:      return null;  
14:    }  
15:    public void addCat (Cat cat) {  
16:      try {  
17:        try {  
18:          utx.begin();  
19:          entityManager.persist(cat);  
20:        } finally {  
21:          utx.commit();  
22:        }  
23:      } catch (Exception e) {  
24:        try {  
25:          utx.rollback();  
26:        } catch (SystemException se) {  
27:          throw new RuntimeException(se);  
28:        }  
29:        throw new RuntimeException(e);  
30:      }  
31:    }  
32:  }  

For the begining it's enough for us to implement just one of the methods, then we will add more specific code.

To declare Entity manager we create class Resources in %PROGECT%/main/java/org/jboss/cats/:
1:  package org.jboss.cats;  
2:    
3:  import javax.enterprise.context.RequestScoped;  
4:  import javax.enterprise.inject.Produces;  
5:  import javax.faces.context.FacesContext;  
6:  import javax.persistence.EntityManager;  
7:  import javax.persistence.PersistenceContext;  
8:    
9:  public class Resources {  
10:    @PersistenceContext  
11:    @Produces  
12:    private EntityManager em;  
13:    
14:    
15:    @Produces  
16:    @RequestScoped  
17:    public FacesContext getFacesContext() {  
18:      return FacesContext.getCurrentInstance();  
19:    }  
20:  }  
21:    
Now annotation @Inject is avalibale for us.

In %PROGECT%/main/resources/META-INF we create persistence.xml to include datasource:

1:  <?xml version="1.0" encoding="UTF-8"?>  
2:    
3:  <persistence version="2.1"  
4:         xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
5:         xsi:schemaLocation="  
6:      http://xmlns.jcp.org/xml/ns/persistence  
7:      http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">  
8:    <persistence-unit name="primary">  
9:      <!-- If you are running in a production environment, add a managed  
10:        data source, this example data source is just for development and testing! -->  
11:      <!-- The datasource is deployed as WEB-INF/greeter-quickstart-ds.xml,  
12:        you can find it in the source at src/main/webapp/WEB-INF/greeter-quickstart-ds.xml -->  
13:      <jta-data-source>java:jboss/datasources/ExampleDS</jta-data-source>  
14:      <properties>  
15:        <!-- Properties for Hibernate -->  
16:        <property name="hibernate.hbm2ddl.auto" value="create-drop" />  
17:        <property name="hibernate.show_sql" value="false" />  
18:      </properties>  
19:    </persistence-unit>  
20:  </persistence>  

Almost all is done, now we need to add a page controller which will generate dynamic content of the page. Put it in the folder %PROGECT%/main/java/org/jboss/cats/web:


1:  package org.jboss.cats.web;  
2:    
3:  import org.jboss.cats.domain.Cat;  
4:  import org.jboss.cats.domain.CatDao;  
5:    
6:  import javax.enterprise.context.RequestScoped;  
7:  import javax.enterprise.inject.Produces;  
8:  import javax.faces.application.FacesMessage;  
9:  import javax.faces.context.FacesContext;  
10:  import javax.inject.Inject;  
11:  import javax.inject.Named;  
12:    
13:  @Named  
14:  @RequestScoped  
15:  public class AddController {  
16:    
17:    @Inject  
18:    private FacesContext facesContext;  
19:    
20:    @Inject  
21:    private CatDao catDao;  
22:    
23:    @Named  
24:    @Produces  
25:    @RequestScoped  
26:    private Cat newCat = new Cat();  
27:    
28:    public void add() {  
29:      try {  
30:        catDao.addCat(newCat);  
31:        String message = "A new user with id " + newCat.getId() + " has been created successfully";  
32:        facesContext.addMessage(null, new FacesMessage(message));  
33:      } catch (Exception e) {  
34:        String message = "An error has occured while creating the user (see log for details)";  
35:        facesContext.addMessage(null, new FacesMessage(message));  
36:      }  
37:    }  
38:  }  

And  we are done with the backend of our application. The frontend is going to be very simple. In
%PROJECT%/src/main/webapp folder we create template.xhtml (we need it for future when we add more pages) and main.xhtml to show our output form:

template.xhtml:
 <?xml version="1.0" encoding="UTF-8"?>  
 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"  
     "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">  
 <html xmlns="http://www.w3.org/1999/xhtml"  
    xmlns:h="http://xmlns.jcp.org/jsf/html"  
    xmlns:ui="http://xmlns.jcp.org/jsf/facelets"  
    xmlns:f="http://xmlns.jcp.org/jsf/core">  
 <f:view>  
   <h:outputLabel value="Hello, world"/>  
 </f:view>  
   
 <head>  
   <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />  
   <title>Cat shelter</title>  
   <ui:insert name="head" />  
 </head>  
   
 <body>  
   
 <div id="container">  
   <div id="header"></div>  
   
   <div id="sidebar"></div>  
   
   <div id="content">  
     <ui:insert name="content" />  
   </div>  
   
   <br style="clear: both" />  
 </div>  
   
 </body>  
 </html>  

main.xhtml:


 <?xml version="1.0" encoding="UTF-8"?>  
 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"  
     "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">  
 <html xmlns="http://www.w3.org/1999/xhtml"  
    xmlns:h="http://xmlns.jcp.org/jsf/html"  
    xmlns:ui="http://xmlns.jcp.org/jsf/facelets"  
    xmlns:f="http://xmlns.jcp.org/jsf/core">  
   
   
 <ui:composition template="template.xhtml">  
   <ui:define name="content">  
     <h:messages />  
     <h:form>  
       <h:panelGrid columns="3">  
         <h:outputLabel for="name">Enter cat's name:</h:outputLabel>  
         <h:inputText id="name" value="#{newCat.name}" />  
         <h:message for="name" />  
   
         <h:outputLabel for="color">Enter color:</h:outputLabel>  
         <h:inputText id="color" value="#{newCat.color}" />  
         <h:message for="color" />  
   
         <h:outputLabel for="fluffy">Enter age:</h:outputLabel>  
         <h:inputText id="fluffy" value="#{newCat.age}" />  
         <h:message for="fluffy" />  
   
       </h:panelGrid>  
       <h:commandButton action="#{addController.add}"  
                value="Add User" />  
     </h:form>  
     <h:link outcome="/allcats.xhtml">See the cat's we have!</h:link>  
   </ui:define>  
 </ui:composition>  
 </html>  

Let's deploy our application to WildFly server.
Open command prompt and go to the project's root directory. There type:

mvn package wildfly:deploy

The result we can see at the adress: http://localhost:8081/catshelter-java/main.xhtml
Here is working code you can download and try. If you have any problems feel free to ask in comments.

See you here next time to implement ManagingBean and to add more functionality to our cat's shelter application!

No comments:

Post a Comment