Monthly Archives: January 2013

Deploy artifacts to your local Nexus server

In my company, I set up a few maven projects and host a Nexus service on our local server.
Now, we’re starting to have dependencies between the projects. Rather than have everyone download all the project source code, I deployed the maven projects to Nexus.

Here’s what you need to know. I’ll just link to this blog since it’s self-contained and I don’t have anything new to add.
Click here: http://www.stefanolocati.it/blog/?p=1034

Once you have all the configuration files set up, you just type the following command to deploy

mvn deploy

The jars and poms will be pushed to either the releases or snapshot repository depending on the version in your pom.xml. If it contains the word SNAPSHOT, then it’ll be posted to the snapshot repository with a timestamp.

Advertisements
Tagged ,

Reasons why I hate Ubuntu: configuring apache

On the Mac, adding the mod_proxy module was as simple as adding a single line to a configuration file. On ubuntu, it’s a lot less obvious.

Here’s what you need to do
1) Install the modules:

sudo apt-get install libapache2-mod-proxy-html
apt-get install libxml2-dev

If you get an error with apt-get install, you may need to update the indexes:

apt-get update

Some people say you can just softlink the available modules to the enabled modules, which are located at /etc/apache2/mods-available and /etc/apache2/mods-enabled, respectively.
But I could not find the required modules under the mods-available and I wasn’t sure what other submodules were needed.
2) Supposedly having the softlinks in mods-enabled should load it without having to add “LoadModule” commands into the apache2 configuration, but that is not the case.
For me, the following 3 lines were needed:

LoadModule  proxy_http_module    /usr/lib/apache2/modules/mod_proxy_http.so
LoadModule  headers_module       /usr/lib/apache2/modules/mod_headers.so
LoadFile    /usr/lib/libxml2.so

In addition, you need to set the reverse proxy urls

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

Where do you put this? Well, there are several places. Here’s a full list.
I decided to put it in /etc/apache2/httpd.conf

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 , , , ,

A (not so) simple web architecture. Part III. Cross-Domain Configuration

Previously, you were shown how to set up a java REST service and a javascript webpage to call the service. This assumed that the webpage resides on the same server as the REST service. If you were to move that page to another server, say an apache server to do some work on php, then you might find a strange error such as

XMLHttpRequest cannot load http://localhost:8080/kodingnotes/rest/foo/read?input=blah. Origin http://localhost is not allowed by Access-Control-Allow-Origin.

It violates the same origin page policy. Basically, “Under the same origin policy, a web page served from server1.example.com cannot normally connect to or communicate with a server other than server1.example.com. An exception is the HTML <script> element”

Here’s your solution: jsonp

Here’s the quick cheat sheet of what you need to do.

On the Server side
Fortunately, Jersey supports jsonp. You just need to create a wrapper method that returns the json in a padded script like so:

@GET
@Produces({"application/x-javascript"})
@Path("/read/jsonp")
public JSONWithPadding getFooP(
    @QueryParam("callback") @DefaultValue("fn") String callback,
    @QueryParam("input") String input) {
	return new JSONWithPadding(new GenericEntity<Foo>(getFoo(input)) {},
								   callback);
}

On the client side
You just need to redirect your url to the jsonp version and modify the dataType to “jsonp”

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

function getFoo(input) {
  $.ajax({
    type: "GET",
    dataType: "jsonp",
    url: matchUri + "?input=" + input,
    success: function(data){
       alert("Success");
    }
 });
}
Tagged , ,

A simple web architecture. Part II. The client.

And without further ado, here’s the client part.

You just need some javascript in an html file like this:

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

function getFoo(input) {
  $.ajax({
    type: "GET",
    dataType: "json",
    url: matchUri + "?input=" + input,
    success: function(data){
       alert("Success");
    }
 });
}
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 , , , ,

maven: Package [com.package…] does not exist

I sometimes forget how maven works. When you have multiple projects and dependencies among time, sometimes you need to “install” the other artifact before it can be used.

In the dependent project, type:

mvn clean
mvn compile
mvn install

Then from the depending project, you can successfully type:

mvn package
Tagged

Argument list too long

When you try to do any operation in unix (eg. tar, mv, cp) that involves too many arguments (or filenames), then you might get an “Argument list too long” error.

Here’s a solution:

1. Create a file with all the arguments (or filenames).

ls -1 &gt; filenames.txt

2. Use xargs command to read in the file and pipe it into the unix command you’re executing.

xargs -a filenames.txt mv -t /otherfolder/.

There are several ways around this. You can also write a for loop in a script and some commands let you use a file as arguments.
For example, the tar command can be executed as

tar -cvzf archive.tar.gz --files-from filenames.txt
Tagged

Finding substrings very very quickly

Let’s say you’ve got a large document of text, and someone gives you a very large set of words to find in this very large document of text.

What’s the dumbest way to find those words in the document?

Dumbest way:
for each word, scan the document for it

If there are S words in the set and D words in the document, then there would be S*D comparisons. That’s a lot. Maybe you’re thinking about optimizing this by scanning the document once and indexing the D words into a hashtable and then do D lookups in it. That would be better, but still slow if the set of words is very very large. Also, if the things you were looking for didn’t end on word boundaries, you won’t be able to index the document in this way.

Much better way:
The Aho-Corasick string matching algorithm was invented just for this job! Instead of creating an efficient lookup data structure on the document, it creates an efficient lookup data structure on the set of lookup words. The basic idea is that it creates a trie-like data structure for every character of the lookup words. With this, it can match all the lookup words simultaneously with one pass of the document! The complexity is linear to the number of characters in the lookup words, the length of the document and the number of matches. And Linear is good.

Here’s the dry definition from wikipedia

Here’s a neat animation of the algorithm in action.

The best part, this is such a standard data structure and algorithm that somebody else has already written it for you. Here’s a java version of it with a really intuitive API.

AhoCorasick tree = new AhoCorasick();
tree.add(".", ".".toCharArray());
tree.add("...", "...".toCharArray());

tree.prepare();
Iterator&lt;SearchResult&gt; it = tree.search("Questa prova è molto cattiva..".toCharArray());
while(it.hasNext()) {
    SearchResult sr = it.next();
    System.out.println(sr.getLastIndex());

    Set&lt;Object&gt; outputs = sr.getOutputs();

    for(Object s : outputs)
        System.out.println(new String((char[]) s));
}