home.


Tagged: tomcat


Tomcat 7: Deploying from the command line with Tomcat Manager

You can deploy a WAR from the command line with wget:

    wget --http-user=tomcat --http-password=tomcat "http://localhost:8080/manager/text/deploy?war=file:/some/path/SomeWar.war&path=/SomeWar" -O -

You’re entering your manager username and password, along with the path for the deployed war. “-O -” means output to STDOUT. The war part is pointing to the war file on the filesystem.

You can undeploy a war similarly.

    wget --http-user=tomcat --http-password=tomcat "http://localhost:8080/manager/text/undeploy?path=/SomeWar" -O -

This assume you’ve setup your tomcat manager username and password, and given yourself access to the manager-script group in the tomcat-users.xml file, i.e:

    <user username="tomcat" password="tomcat" roles="manager-gui,admin-gui,manager-script"/>
java tomcat-manager unix unix-wget

Tomcat 7: Setting up JSF 2

Ensure you have the JSF reference implementation. Using gradle this would be:

    compile 'com.sun.faces:jsf-api:2.1.19'
    compile 'com.sun.faces:jsf-impl:2.1.19'

In your web.xml file you must have:

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app version="3.0"
          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_3_0.xsd">
          <servlet>
         <servlet-name>Faces Servlet</servlet-name>
         <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
         <load-on-startup>1</load-on-startup>
          </servlet>
          <servlet-mapping>
         <servlet-name>Faces Servlet</servlet-name>
         <url-pattern>/faces/*</url-pattern>
          </servlet-mapping>
          <welcome-file-list>
         <welcome-file>faces/hello.xhtml</welcome-file>
          </welcome-file-list>
    </web-app>

This includes the faces servlet, and sets up a serlvet mapping that intercepts anything that has the faces/* url. Our welcome file will be hello.xhtml.

In our WEB-INF/ folder we now need to define that hello.xhtml file:

    <?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 lang="en"
          xmlns="http://www.w3.org/1999/xhtml"
          xmlns:h="http://java.sun.com/jsf/html">
        <h:head>
       <title>Facelets Hello World</title>
        </h:head>
        <h:body>
       Hiya
        </h:body>
    </html>

Now the differing h namespace that includes all the JSF tags. We’ll look at those later.

Now if you go to http://localhost:8080/YOUR_WAR_NAME/faces/index.xhtml you’ll see your face. http://localhost:8080/YOUR_WAR_NAME/ will go to the same thanks to the welcome-file-list above.

tomcat tomcat-jsf jsf-setup jsf

Tomcat 7: REST services with Jersey

First download Apache Jersey. I downloaded the archive with the follow jars in them and placed them in /usr/share/tomcat7/lib and restarted tomcat.

 asm-3.1.jar
 jackson-core-asl-1.9.2.jar
 jackson-jaxrs-1.9.2.jar
 jackson-mapper-asl-1.9.2.jar
 jackson-xc-1.9.2.jar
 jersey-client-1.17.jar
 jersey-core-1.17.jar
 jersey-json-1.17.jar
 jersey-server-1.17.jar
 jersey-servlet-1.17.jar
 jettison-1.1.jar
 jsr311-api-1.1.1.jar

I had to increase Tomcat’s memory size to avoid out of memory errors. I put this line at the top of /usr/share/tomcat7/bin/catalina.sh

JAVA_OPTS=‘-Xmx512m’

Then you can create a simple POJO with the @XMLRootElement annotation. This will allow it to be converted into JSON for the REST services (Yes, it does say XMLRoot…)

 @XmlRootElement
 public class JsonObject {
   private String str;
   public String getStr() {
      return str;
   }
   public void setStr(String str) {
      this.str = str;
   }
 }

Next you can create your REST class by creating a class like the following:

 @Path("/rest")
 public class Rest {
   @Context
   UriInfo info;
   @Context
   Request request;
   @Context
   ServletContext context;
   ...
   @PostConstruct
   public void init() {
   }
 }

This defines a new rest api that will have the ‘/rest/’ prefix. The @Context annotation injects UriInfo and details of the actual request that you may want to use. You can access these methods in a method annotated with @PostConstruct

The real logic comes in the method signatures:

 @GET
 @Path("/r")
 @Produces(MediaType.TEXT_PLAIN)
 public String sayRest() {
   return "rest";
 }

 @GET
 @Path("/r")
 @Produces(MediaType.TEXT_HTML)
 public String sayRest() {
   return "html text";
 }

This will produce different responses, depending on whether the client is asking for plain text or html. The path is /rest/r.

This produces and consumes the POJO object we created above:

 @PUT
 @Path("/j")
 @Produces(MediaType.APPLICATION_JSON)
 @Consumes(MediaType.APPLICATION_JSON)
 public JsonObject intakeJson(JsonObject intake) {
   intake.setStr("intaken: " + intake.getStr());
   return intake;
 }

You can either pass in query parameters or path parameters:

 @GET
 @Path("/r")
 @Produces(MediaType.TEXT_HTML)
 public String sayRestInHtml(@QueryParam("q") String q) {
   return "rest: "+q;
 }  

 @GET
 @Path("/r/{q}")
 @Produces(MediaType.TEXT_HTML)
 public String sayRestInHtmlWithPath(@PathParam("q") String q) {
   return "rest with param: "+q;
 }

You’d access these via /rest/r?q=sdfsdf and /rest/r/sdfsdf.

You can craft HTTP responses using:

 Response.created(info.getAbsolutePath()).build();

This creates a CREATED HTTP response with the absolute path gained from the UriInfo via the @Context annotation above.

You now need to edit your web.xml to activate this servlet:

  <servlet>
    <servlet-name>Jersey REST Service</servlet-name>
    <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
    <init-param>
      <param-name>com.sun.jersey.config.property.packages</param-name>
      <param-value>org.denevell.tomcat.rest</param-value>
    </init-param>
    <init-param>
      <param-name>com.sun.jersey.api.json.POJOMappingFeature</param-name>
      <param-value>true</param-value>
    </init-param>         
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>Jersey REST Service</servlet-name>
    <url-pattern>/rest/*</url-pattern>
  </servlet-mapping>

This is a normal servlet mapping except the servlet-class is a Jersey class, and the init-param state where the REST class is. And the com.sun.jersey.api.json.POJOMappingFeature ensures you use Jackson instead of the standard Java implementation JaxB (which you don’t want).

You final urls will be such as

 /rest/rest/r
jersey java REST servlet tomcat

Tomcat 7: JPA using EclipseLink and Sqlite

Download EclipseLink, the reference implementation for JPA, from http://www.eclipse.org/eclipselink/downloads/ and the sqlite jdbc library, from https://bitbucket.org/xerial/sqlite-jdbc/downloads.

Copy, eclipselink.jar, javax_persistence_2.x.x.jar and the sqlite jdbc jar file into your tomcat lib directory, /usr/share/tomcat7/lib in my case.

Now restart tomcat.

Create persistence.xml in src/META-INF/persistence.xml.

  <?xml version="1.0" encoding="UTF-8" ?>
  <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_2_0.xsd"
      version="2.0"
      xmlns="http://java.sun.com/xml/ns/persistence">
    <persistence-unit name="example" transaction-type="RESOURCE_LOCAL">
      <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
      <class>org.denevell.tomcat.entities.write.AnotherThing</class>
      <properties>
        <property name="javax.persistence.jdbc.driver" value="org.sqlite.JDBC" />
        <property name="javax.persistence.jdbc.url" value="jdbc:sqlite:/var/lib/tomcat7/dbs/test.db" />
        <property name="eclipselink.logging.level" value="ALL" />
        <property name="eclipselink.ddl-generation" value="create-tables" />
      </properties>
    </persistence-unit>
 </persistence>

The persistence-unit name will be how we will grab a hold of our persistence entity manager factory. The transaction-type say we’re using a local database. If it said JTA it would mean we’d have support for transactions over multiple datasources (Tomcat doesn’t support this out of the box).

We next tell it about the provider, EclipseLink, in our case. Then the class that will be persisted. Then we set properties to tell it about our driver, our jdbc url, the logging level and how we will generate the database.

We could set eclipselink.ddl-generation to ‘drop-and-create-tables’ if we want to destroy the database everytime. In a later tutorial we’ll detail how to work with an existing database without automatically doing anything, since the eclipselink.ddl-generation is only really useful during development.

Here’s what our ‘AnotherThing’ entity looks like:

package org.denevell.tomcat.entities.write; // Referenced in persistence.xml

@Entity
public class AnotherThing {
  @Id @GeneratedValue
  private int id;
  private String text;
  public AnotherThing() {
  }
  public int getId() {
      return id;
  }
  public void setId(int id) {
      this.id = id;
  }
  public String getText() {
      return text;
  }
  public void setText(String text) {
      this.text = text;
  }
}

Note @Entity defines our class as just that, the @Id annotation says this is the primary key of the entity, and @GeneratedValue say the persistence provider generates its value.

We can now talk to our JPA instance:

// Setup the entity manager
EntityManagerFactory factory =   Persistence.createEntityManagerFactory("example");
EntityManager em = factory.createEntityManager();
// Create it
AnotherThing t = new AnotherThing();
t.setText("Heya");      
// Add it
EntityTransaction trans = em.getTransaction();
trans.begin();
em.persist(t);
trans.commit();
// Fetch them
TypedQuery<AnotherThing> q = em.createQuery("select ting from AnotherThing ting", AnotherThing.class);
List<AnotherThing> results = q.getResultList();
for (AnotherThing thing : results) {
  writer.println(thing.getId() + ": " + thing.getText());
}
// Close the entity manager
em.close();
factory.close();

Note we’re using our name of the persistence-unit above to get the entity manager factory. Then we get the entity manager (we should only have one of these). Then we create a new object as normal.

We then start an entity transaction (we could use this to rollback if we wanted). Then we persist the object, committing the transaction.

Finally we use the JPQL syntax to get all the ‘AnotherThing’ objects in the database. Then we close the entity manager, and the entity manager factory.

I did get some error about AnotherThing not being recognised. Unfortunatley I think this is a bug in Tomcat for the most part. Stopping and then starting Tomcat should resolve the problem.

java jpql jpa tomcat sql sqlite

Tomcat 7: JDBC via JNDI using sqlite

First download the sqlite jdbc driver from https://bitbucket.org/xerial/sqlite-jdbc/downloads and copy it into your lib/ folder in your tomcat directory, /usr/share/tomcat7/lib/. Then restart tomcat so it can find your new jar.

Then add a reference to a new jdbc resource in your web/META-INF/context.xml file. It defines a JNDI name, its class type, the driver class name that relates to the jar we just installed above, and a url to connect to the database. In my case I’m pointing to a directory (which must exist) on the file system.

<Context>
    <Resource name="jdbc/sqlite"
    type="javax.sql.DataSource"
    driverClassName="org.sqlite.JDBC"
    url="jdbc:sqlite:/var/lib/tomcat7/dbs/test.db"
    />
</Context>

In addition, you have to add the resource in your web.xml file. Note the name is the same the name above.

...
<resource-ref>
    <res-ref-name>jdbc/sqlite</res-ref-name>
    <res-type>javax.sql.DataSource</res-type>
</resource-ref>
...

Now you can make reference to the database in your Java code. This is lifted from the sqlite example page:

Connection conn = null;
try {
    Context ctx = new InitialContext();
    DataSource ds = (DataSource) ctx.lookup("java:comp/env/jdbc/sqlite");
    conn = ds.getConnection();
    Statement statement = conn.createStatement();
try {
    statement.executeUpdate("create table thing(x integer)");
} catch (Exception e) { 
     // Could well be already there
}
statement.executeUpdate("insert into thing values(42)");
ResultSet rs = statement.executeQuery("select * from thing");
while (rs.next()) {
writer.println("id = " + rs.getInt(1));
} catch (Exception e) {
    writer.println(e.getMessage());
} finally {
    try {
        if (conn != null) conn.close();
    } catch (SQLException e) {
        writer.println(e);
    }
}
java tomcat-jndi tomcat-jdbc jdbc sql sqlite tomcat

Page 2 of 3
Previous Next