Tag Archives: tomcat

Tomcat ContextPath and Angularjs

An interesting obstacle arose when I tried to use Angularjs (NG) in Tomcat, specifically in regards to the path.

Typically, I’ve been using NG assuming everything starts at the root path. So my index.html is at http://domain.com/index.html.

However, in Tomcat, each webapp has its own starting path. So you may have a weather webapp that is at http://domain.com/weather/ and a clock webapp at http://domain.com/clock/.

How do you configure NG within tomcat?

You could hardcode your starting path. But imagine if you wanted to have two clock webapps in tomcat, renaming one to http://domain.com/clock1/ and the other http://domain.com/clock2.

Now you would have to change all the references of “clock” to “clock1” and “clock2” respectively. And there are many references…

In the index.html, you have to change all your <link …css> as well as all <script …js>. You might think that you can outsmart yourself by changing the index.html to a index.jsp and using <%=request.getContextPath()%>.

But then you still have to change references of the hardcoded path in your .js files, such as your app.js that defines your module and routes.

And don’t even get me started on all your templates that reference .js and .css.

Well, let me jump straight to the short answer.

In your index.html, simply add this within your <head> tag

<head>
    <base href="/clock/" />
</head>

That’s it. Now all your relative paths will have that base href prefixed to them automatically.

So <link href=”mystyle.css”> will automatically fetch from http://domain.com/clock/mystyle.css

<script src=”myscripts.js>” will automatically fetch from http://domain.com/clock/myscripts.js

Even app.js will leverage this base when using relative url’s.
e.g. $routeProvider.when(‘/’, {templateurl: ‘home.html’})
will automatically reference http://domain.com/clock/home.html

This html standard can even be used on jsp pages. Anything that is html will take advantage of it

Tagged , , ,

Setting up Tomcat for debugging

Short PSA. If you want to set up Tomcat for debugging, set up JPDA.

To do so, simply open the startup.sh file, which is somewhere in TOMCAT/bin folder.

Add these two lines near the top

export JPDA_ADDRESS=7000
export JPDA_TRANSPORT=dt_socket

Then modify the exec line (usually the last line in the file) from this:

exec "$PRGDIR"/"$EXECUTABLE" start "$@"

to this

exec "$PRGDIR"/"$EXECUTABLE" jpda start "$@"
Tagged ,

Upgrading to Jersey 2.x in Tomcat8

Jersey 1.x is still supported. As of this writing, version 1.19.3 was just released on Oct 24th, 2016.

But recently I discovered that Tomcat8 doesn’t play well with Jersey 1.x so we simply have to upgrade to Jersey 2.x. Easy right? (If it were, I wouldn’t be writing this post.)

Jersey 1.x
Let’s review the Jersey 1.x configurations first

As far as maven dependencies, here’s what I used in my pom.xml

<dependency>
  <groupId>com.cedarsoft.rest</groupId>
  <artifactId>jersey</artifactId>
  <version>1.0.0</version>
</dependency>

<dependency>
  <groupId>com.sun.jersey</groupId>
  <artifactId>jersey-json</artifactId>
  <version>1.5</version>
</dependency>

com.cedarsoft.rest:jersey is a bundle that includes these dependencies.

Unfortunately, I could find no such bundle for Jersey 2.x so I had to mix and match until trial-and-error led me to a workable solution. (I save you the trouble.)

Here’s my old web.xml

<web-app version="2.4"
 xmlns="http://java.sun.com/xml/ns/j2ee"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
  <servlet>
    <servlet-name>JerseyREST</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>INSERT_MY_PACKAGES_AND_CLASSES_HERE</param-value>
    </init-param>
    <load-on-startup>2</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>JerseyREST</servlet-name>
    <url-pattern>/rest/*</url-pattern>
  </servlet-mapping>
</web-app>

Jersey 2.x
Now here are the changes for Jersey 2.

   <dependency>
     <groupId>javax.servlet</groupId>
     <artifactId>javax.servlet-api</artifactId>
     <version>3.1.0</version>
     <scope>provided</scope>
   </dependency>
   <dependency>
     <groupId>org.glassfish.jersey.containers</groupId>
     <artifactId>jersey-container-servlet-core</artifactId>
     <version>2.13</version>
   </dependency>
   <dependency>
     <groupId>org.glassfish.jersey.containers</groupId>
     <artifactId>jersey-container-servlet</artifactId>
     <version>2.13</version>
   </dependency>
   <dependency>
     <groupId>com.fasterxml.jackson.core</groupId>
     <artifactId>jackson-databind</artifactId>
     <version>2.8.5</version>
   </dependency>
   <dependency>
     <groupId>org.glassfish.jersey.media</groupId>
     <artifactId>jersey-media-json-jackson</artifactId>
     <version>2.13</version>
   </dependency>
   <!-- jersey file upload dependencies -->
   <dependency>
     <groupId>org.glassfish.jersey.media</groupId>
     <artifactId>jersey-media-multipart</artifactId>
     <version>2.13</version>
   </dependency>

org.glassfish.jersey.media:jersey-media-multipart is only required for file upload capability.

Here’s the new web.xml

<web-app version="3.1"
         metadata-complete="false"
         xmlns="http://java.sun.com/xml/ns/j2ee"
         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">
  <servlet>
    <servlet-name>JerseyREST</servlet-name>
    <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
    <init-param>
        <param-name>jersey.config.server.provider.classnames</param-name>
        <param-value>org.glassfish.jersey.media.multipart.MultiPartFeature</param-value>
    </init-param>        
    <init-param>
      <param-name>jersey.config.server.provider.packages</param-name>
      <param-value>
        INSERT_MY_PACKAGES_AND_CLASSES_HERE
      </param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
      <servlet-name>JerseyREST</servlet-name>
      <url-pattern>/rest/*</url-pattern>
  </servlet-mapping>
</web-app>

Notice, the new servlet class.
It’s also important to load the org.glassfish.jersey.media.multipart.MultiPartFeature to support file upload capability.

You might also have to change some of your code.
For example, all your @JsonIgnore annotation classes will have to change from
org.codehaus.jackson.annotate.JsonIgnore
to
import com.fasterxml.jackson.annotation.JsonIgnore

Tagged ,

Quick Ubuntu 16 Setup with java8, mysql 5.7, tomcat7

sudo apt-get update

# get latest java, which is java8 at time of writing
sudo apt-get install default-jdk

# get latest mysql, which is mysql5.7 at time of writing
sudo apt-get install mysql-server

# get tomcat7
sudo apt-get install tomcat7
Tagged , , ,

A (not so) simple web architecture. Part IIIb. Proxying requests

In the previous posts, I showed you how to use jsonp to bypass browser restrictions that prevent a webpage on one server (apache) from accessing resources on another (tomcat). jsonp works will but it has restrictions of its own, such as, it only allows GET. So you can’t use the full language of REST (POST, PUT, DELETE). And really, is it still REST then?

There’s a hack to get around that, but compounding hacks on top hacks is rarely a good idea unless you have a lot of old coffee grind you need to use up.

Another solution is to use the webpage’s server as a proxy server. Apache lets you do that with two modules: mod_jd and mod_proxy.

I won’t get too much into them, but here’s a short comparison I found:
mod_proxy
Pros:

  • No need for a separate module compilation and maintenance. mod_proxy, mod_proxy_http, mod_proxy_ajp and mod_proxy_balancer comes as part of standard Apache 2.2+ distribution
  • Ability to use http https or AJP protocols, even within the same balancer.

Cons:

  • mod_proxy_ajp does not support large 8K+ packet sizes.
  • Basic load balancer
  • Does not support Domain model clustering

mod_jk
Pros:

  • Advanced load balancer
  • Advanced node failure detection
  • Support for large AJP packet sizes

Cons:

  • Need to build and maintain a separate module

I decided to use mod_proxy because the module comes built into apache, which means less configuration and less possibility of error.

Here’s how simple it was to set up.
I added one line to the httpd.conf file under the main directive:

ProxyPass /pass/ http://localhost:8080/

That tells apache (served at http://localhost) that whenever a client makes a request for http://localhost/pass/ to redirect that to http://localhost:8080/.

The only slight change is the url of the call in javascript from

var matchUri = "http://localhost:8080/kodingnotes/rest/foo/read/jsonp";

to

var matchUri = "http://localhost/pass/kodingnotes/rest/foo/read";

Now, I can use the original (non-jsonp) jQuery call and apache will forward the request to the non-JXONWithPadding wrapper java method.

Tagged , , , ,

I’m not going to go over all the reasons why you should have a RESTful service with javascript front-end (e.g. clean separation of front- and back-end, reusable web service components, etc). Here I’ll just show how you can quickly set up a RESTful web service in Java and a javascript/jQuery front-end to access it.

The server part requires just 4 things:
1) Add Jersey dependency
2) Write a java bean and annotate it
3) Write a Service class
4) Deploy the servlet in web.xml

1) Add Jersey dependency

If you’re using Maven, then add the following Jersey (JAX-RS implementation) dependency to your pom.xml

<dependency>
    <groupId>com.cedarsoft.rest</groupId>
    <artifactId>jersey</artifactId>
    <version>1.0.0</version>
    <scope>compile</scope>
</dependency>


2) Write a java bean and annotate it

Create a java bean with the following:
1) annotate the class with @XmlRootElement
2) make sure there’s a null constructor (no arguments)
3) add public setters/getters

import javax.xml.bind.annotation.XmlRootElement
@XmlRootElement
public class Foo {
    private String name;
    public Foo() { }
    public String getName() { return name; }
    public void setName(String s) { name = s; }
}

3) Write a Service class

package com.kodingnotes.services;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;

@Path ("/foo")
@Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
public class FooService {

    @GET
    @Path("/read")
    public Foo getFoo(@QueryParam("input") String input) {
        Foo foo = new Foo();
        foo.setName(input);
        return foo;
    }
}

4) Deploy the servlet in web.xml

In your web.xml, add the following servlet


<servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
  <init-param>
    <param-name>com.sun.jersey.config.property.packages</param-name>
    <!-- ##### REFER TO THE PACKAGE WHERE YOU WANT JERSEY TO PICK UP THE RESOURCE CLASSES ###### -->
    <!-- ##### Use semi-colon to specify multiple packages ###### -->
    <param-value>com.kodingnotes.services</param-value>
  </init-param>
  <init-param>
    <param-name>com.sun.jersey.spi.container.ContainerRequestFilters</param-name>
    <param-value>com.sun.jersey.api.container.filter.GZIPContentEncodingFilter</param-value>
  </init-param>
  <init-param>
    <param-name>com.sun.jersey.spi.container.ContainerResponseFilters</param-name>
    <param-value>com.sun.jersey.api.container.filter.GZIPContentEncodingFilter</param-value>
  </init-param>
  <init-param>
    <param-name>com.sun.jersey.config.feature.logging.DisableEntitylogging</param-name>
    <param-value>false</param-value>
  </init-param>
  <load-on-startup>2</load-on-startup>
</servlet>
<servlet-mapping>
  <servlet-name>JerseyREST</servlet-name>
  <url-pattern>/rest/*</url-pattern>
</servlet-mapping>

 Edit the <param-value> of the <param-name>com.sun.jersey.config.property.packages<param-name>

A simple web architecture. Part I: The Server

Tagged , , , ,