Google App Engine JAX-RS REST service

In this article you will learn how to create a REST service using JAX-RS reference implementation (Jersey) and deploy it on Google AppEngine.

Prerequisites 

For this tutorial you will need:
  • a Google AppEngine account
  • Eclipse Galileo (3.5.x)
  • Google App Engine SDK for Java
    • Install the Google Plugin for Eclipse as documented here (Check that you are using the release 1.3.1 of the GAE Java SDK, if not download it and configure the plugin to use it)
    • it is also useful to have the AppEngine documentation locally, you can download it from here.
  • JAX-RS Reference Implementation, be sure you take the Jersey 1.1.5 release. You can download it from here
    • Unzip the file in a directory that we will call $JERSEY_HOME
  • JAXB 2.2 Implementation to simplify the marshalling/unmarshalling of the XML, and also facilitate the JSON support. Download it from here
    • Install it using thejava -jar JAXB2_20091104.jar command. The installation directory of JAXB will be called $JAXB_HOME



Creating new application

To create a new App Engine project in Eclipse:

  1. Click on the "New Web Application Project" button in the toolbar . It is also possible to do it using the menu File > Web Application Project
  2. The "Create a Web Application Project" wizard opens:
  • Project Name: EmployeeService
  • Package : com.grallandco.employee.service
  • Uncheck "Use Google Web Toolkit"
  • Check that the SDK version your are using is "App Engine 1.3.0"; if not configure the project to use it.
  • The screen should look like the following screen :
  • Click Finish
  • The project should look like the following screen :

Running the application

The App Egine SDK, installed with the Eclipse plugin contains a Web server (based on Jetty), that could be used for testing and debugging. To test that your application has been created correctly select the menu Run > Run As > Web Application. I personnaly most of the time run my server using the debug command Run > DebugAs > Web Application. In debug mode you can change source code and test is without restarting the server.

The web server is starting automatically, you should see the following message in the Eclipse console

The server is running at http://localhost:8080/

You can access the application, and the sample servlet that has been created using the URL: http://localhost:8080/employeeservice

To stop the server, click on the terminate button
in the Eclipse console.

Configuring the REST support in the application

To be able to create and run REST services in your application you need to:

  • Add the JAX-RS, JAXB Jars in your project and application
  • Configure the web application (web.xml) to handle REST requests

Add JAX-RS, JAXB to your project

  1. Right click on the project and select menu entry Build Path > Configure Build Path…
  2. Click on the Add External JARs button
  3. Select all the JARs located in $JERSEY_HOME/lib and $JAXB_HOME/lib folders. You can for better visibility and reuse create a user library with all these JARs
  4. You also need to copy the JARs in the web-inf/lib directory of your application, this step is mandatory to be sure that the JARs are included in the application when deployed to App Engine.
    Note: I do not like this step. I would prefer to do that by configuration of the build path, to automatically add the JARs to the WEB-INF/lib directory when executing/deploying the application. Unfortunately I did not find the way to do it, so if you know it, feel free to post a comment and I will update the article.

Configure the web application

In this step you will register a new URI to handle REST requests. To do that you need to register a new servlet that is using the Jersey API and configure it to a specific URI (eg: /ressources and/or /rest) and configure what are the Java packages that contain the REST implementation classes. So you need to modify the web.xml of your application with the following entries:

  <servlet>
    <servlet-name>Jersey Web Application</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>com.grallandco.employee.service.rest.impl</param-value>
     </init-param>
     <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>Jersey Web Application</servlet-name>
    <url-pattern>/resources/*</url-pattern>
  </servlet-mapping>
   <servlet-mapping>
    <servlet-name>Jersey Web Application</servlet-name>
    <url-pattern>/rest/*</url-pattern>
  </servlet-mapping>
This servlet that will answer to the /resources/ and /rest/ URL. The configuration parameter com.sun.jersey.config.property.packages is used by Jersey to list the packages where REST services implementation are located.Note that you can put as many package as you need to, you just need to separate the package names by a ; 


Creating a simple REST Service to test the environment

The project is now ready to contain REST service. It is time to create one.Create for example the class com.grallandco.employee.service.rest.impl.HelloWorldResource, be sure to use the package name that you have configured in the web.xml for the Jersey servlet, based on the configuration we have made in previous step the package is com.grallandco.employee.service.rest.impl

Here a sample class with the JAX-RS annotations:

package com.grallandco.employee.service.rest.impl;
import javax.ws.rs.Path;
import javax.ws.rs.GET;
import javax.ws.rs.Produces;
@Path("/hr/")
public class EmployeeResource {
 
 @GET
 @Produces("text/plain")
 @Path("/employee") 
 public String getEmployee() {
        return "Hello World!";
    }
}

You should be able to test it, stop the server and run it again, enter the following URL in your browser:

http://localhost:8080/resources/hr/employee

or

http://localhost:8080/rest/hr/employee

Deploying the application to Google App Engine

Before deploying the application you need to register a new application in Google App Engine using the Administartion Console, see the documentation
here. In my example I have used " tugdual" as Application ID.

You can easily now deploy the application to Google App Engine by clicking on the "Deploy App Engine Project" button available in the Eclipse toolbar.

To be able to deploy your application to Google App Engine, you need to check that your application can be registered, the application ID is stored in the WEB-INF/lib/appengine-web.xml.

<?xml version="1.0" encoding="utf-8"?>
<appengine-web-app xmlns="http://appengine.google.com/ns/1.0">
 <application>[your-application-id]</application>   
 <version>1</version>    
 <!-- Configure java.util.logging -->
  <system-properties>
   <property name="java.util.logging.config.file" value="WEB-INF/logging.properties"/>
 </system-properties>    
</appengine-web-app>

The App Engine deploy button prompts you for multiple informations: username (your Google account) and password.

When the deployment is complete you can access your application using the following URL:

http://%5Byour-application-id%5D.appspot.com/resources/hr/employee

or

http://%5Byour-application-id%5D.appspot.com/rest/hr/employee

Ading XML and JSON support to the service

Let’s now add new method to manipulate an "Employee" object using the service, and the data format should be based on JSON and XML. This is where JAXB is useful, since it allows easily to transform marshall/unmarshall Java objects in XML -obviously- and JSON (cool isn’t!)

Creating an Employee Class

Start with the creation of a new class to manipulate Employee data, this is a very simple Java class that could look like the following code:

package com.grallandco.employee.service.model;
import java.util.Date;

public class Employee {
    private String firstName;
    private String lastName;
    private Date hireDate;
    private String email;   
    public Employee(String firstName, String lastName, Date hireDate, String email) {
        this.firstName = firstName;
        this.lastName = lastName;
        this.hireDate = hireDate;
        this.email = email;
    }
    public Employee() {}
    public String getFirstName() {
 return firstName;
 }
    public void setFirstName(String firstName) {
 this.firstName = firstName;
 }
    public String getLastName() {
 return lastName;
 }
    public void setLastName(String lastName) {
     this.lastName = lastName;
 }
    public Date getHireDate() {
 return hireDate;
 }
    public void setHireDate(Date hireDate) {
 this.hireDate = hireDate;
 }
    public String getEmail() {
        return email;
 }
    public void setEmail(String email) {
        this.email = email;
   }
    public String toString() {
        StringBuffer sb = new StringBuffer();
        sb.append("First: ").append(getFirstName());
        sb.append(" - Last: ").append(getLastName());
        sb.append(" - Date: ").append(getHireDate());
        sb.append(" - Email: ").append(getEmail());
        return sb.toString();
    }
}

When implementing your "real" application with some persistence layer this POJO is the one as JDO/JPA entity.

Create a Converter class for your entity

I usually encapsulate all the transformation in some converter class, like that I do not directly couple my business class to the serialisation mechanism. (So I do that for classes and lists of classes). So instead of adding the JAXB annotations to the Employee class itself, let’s create an EmployeeConverter class that will be responsible of the transformation and used by your REST service.

package com.grallandco.employee.service.converter;

import java.util.Date;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import com.grallandco.employee.service.model.Employee;

@XmlRootElement(name = "employee")
public class EmployeeConverter {
 private Employee entity = null;
 public EmployeeConverter() {
 entity = new Employee();
 }

 public EmployeeConverter(Employee entity) {
 this.entity = entity;
 }

 @XmlElement
 public String getFirstName() {
 return entity.getFirstName();
 }

 @XmlElement
 public String getLastName() {
 return entity.getLastName();
 }

 @XmlElement
 public Date getHireDate() {
 return entity.getHireDate();
 }

 @XmlElement
 public String getEmail() {
 return entity.getEmail();
 }

 public Employee getEmployee() {
 return entity;
 }

 public void setFirstName(String firstName) {
 entity.setFirstName(firstName);
 }

 public void setHireDate(Date hireDate) {
 entity.setHireDate(hireDate);
 }

 public void setLastName(String email) {
 entity.setEmail(email);
 }

 public void setEmail(String lastName) {
 entity.setLastName(lastName);
 }
}

You can now update your service to use this utility/converter class to return XML or JSON ojbect based on the content type of the request.

Add support to JSON and XML to your REST service

You need to change the EmployeeRessource class, to change the signature and add new annotations of the getEmployee() method.

The annotation you are adding:

  • @Produces({"application/xml", "application/json"}) : indicates which type of content will be produced by the service. Based on the type of the request.
  • @Path("/employee/{employeeEmail}/") : change the Path to indicate a Path parameter, here for example the URL can accept an email in the URI – not the best example, but you get the point…
  • public EmployeeConverter getEmployee( @PathParam ("employeeEmail") String email) : change the type returned by the method and take a parameter as String that match the Path param defined in the @Path annotation

Here the complete class code:

package com.grallandco.employee.service.rest.impl;

import javax.ws.rs.Path;
import javax.ws.rs.GET;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import com.grallandco.employee.service.converter.EmployeeConverter;
import com.grallandco.employee.service.model.Employee;

@Path("/hr/")
public class EmployeeRessource {

 
 @GET
 @Produces({"application/xml", "application/json"})
 @Path("/employee/{employeeEmail}/") 
 public EmployeeConverter getEmployee( @PathParam ("employeeEmail") String email) {
 //dummy code
 Employee emp = new Employee();
 emp.setEmail(email);
 emp.setFirstName("John");
 emp.setLastName("Doe");
 EmployeeConverter converter = new EmployeeConverter(emp);
 return converter;
 } 
}

Test the service

You can now run the server locally and test the service

http://localhost:8080/resources/hr/employee/tug@grallandco.com

This will return an XML document.

If you want to test the JSON call you have multiple choice:

  • Using following command
tgrall$ curl -H "Accept: application/json" http://localhost:8080/resources/hr/employee/tug@grallandco.com
{"email":"tug@grallandco.com","firstName":"John","lastName":"Doe"}
  • Using an HTTP client that allows your to configure/set the HTTP request completely, I am using the Poster Firefox Plugin
  • Using some Javascript code in an application

You can repeat the test on your deployed application on Google App Engine.

Conclusion

In this article you have learned how to create and deploy a new REST Service on Google App Engine. This service has been created with the JAX-RS Reference Implementation the Jersey project. In the next article you will learn how to add persistence and create a CRUD Rest service on Google App Engine.


Reference:
Create and Deploy a JAX-RS REST service on Google App Engine from our
JCG partner Tugdual Grall at the
Tug’s Blog blog.

Source : http://www.javacodegeeks.com/2012/05/google-app-engine-jax-rs-rest-service.html

JavaME: Google Static Maps API

Whether you need a map for your location based application or just for fun, you can use the easiest way ever: Google Static Maps API. In this post, we are going to see how you can get a Map as an Image from a latitude and longitude point. The latitude and longitude can be obtained using Location API which we won’t discuss in this post.


When writing this post, I realized there is some license restrictions in the use of Google Static Maps API in mobile Apps… I am posting it anyway just for research purposes, but I must warn you about this restriction:

 


http://code.google.com/intl/en/apis/maps/faq.html#mapsformobile

Google Static Maps API Quick Review


 

This API lets you get an Image based on a URL and several parameters you can pass in to obtain a personalized map. You can play with the zoom, type of map, size of the image (width, height), markers at locations of the map, etc. There is a limit you have to keep in mind, the use of the API is subject to a query limit of 1000 unique (different) image requests per viewer per day, which is a lot of images… but if you need more, there is also a Premium license. For more information:

http://code.google.com/intl/en/apis/maps/documentation/staticmaps/

OK, what we do is the following:

  • Create a method that receives a latitude and longitude point and the size of the image as parameters.
  • Request the map image using the URL: http://maps.googleapis.com/maps/api/staticmap, and adding some parameters.
  • Create an Image object and return it, so we can show it on screen.


Hands on Lab

Following is the method we were talking about. It has parameters for the latitude and longitude, and also for the width and height of the image we are requesting. The latitude and longitude can be retrieved using Location API, and the width and height can be retrieved using the Canvas class.

public Image getMap(double lat, double lon, int width, int height) 
throws IOException 
{
    String url = "http://maps.google.com/maps/api/staticmap";
    url += "?zoom=15&size=" + width + "x" + height;
    url += "&maptype=roadmap";
    url += "&markers=color:red|label:A|" + lat + "," + lon;
    url += "&sensor=true";

    HttpConnection http = (HttpConnection) Connector.open(url);
    InputStream in = null;
    byte[] imgBytes = null;
    try {
        http.setRequestMethod(HttpConnection.GET);
        in = http.openInputStream();

        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        byte[] buffer = new byte[1024];
        int n = 0;
        while ((n = in.read(buffer)) != -1) {
            bos.write(buffer, 0, n);
        }
        imgBytes = bos.toByteArray();
    } finally {
        if (in != null) {
            in.close();
        }
        http.close();
    }
    Image img = Image.createImage(imgBytes, 0, imgBytes.length);

    return img;
}

As you may see, it is pretty simple to get the image of the map. The retrieving is pure HTTP request.

Next you can find an image retrieved by Google Static Maps from a location in my home town.

OK, you just saw how simply it would be if no restriction exists… What do you think about that restriction? It’s kind of confusing, isn’t it?

Anyway, we are going to need to find another way to show maps on our mobile apps.


Reference:
Google Static Maps API and JavaME from our
JCG partner Alexis Lopez at the
Java and ME blog.

Source : http://www.javacodegeeks.com/2012/05/javame-google-static-maps-api.html

Cloud SQL: pick the plan that fits your app

One of the most requested additions to the Google App Engine platform has been a SQL database, and more than 10,000 developers have signed up for the Google Cloud SQL service since the preview launch last October. Google Cloud SQL automatically provisions and maintains your databases, allowing you to focus on your applications and services.






Since launch, we’ve been busy working on improving the performance, and adding features like scheduled backups and multihoming to increase availability and improve performance. We are also now offering more powerful instances with up to 4GB of RAM. 



Today we are announcing our pricing, which will take effect on June 12th with two options to choose from:

  • For developers who want to try out the service, or who have lightweight applications – we offer a flexible “per use” pricing scheme. For example, you can get started with a cloud hosted MySQL database for around a dollar per month. You pay for just what you use.
  • For developers with more traffic, there are packages that offer a discount and help you predict your costs in advance.


Google Cloud SQL is currently in limited preview. If you want to give us a try, start here https://developers.google.com/cloud-sql/.

Posted by Joe Faith on behalf of the Google Cloud SQL team

Source : http://googleappengine.blogspot.ca/2012/05/cloud-sql-pick-plan-that-fits-your-app.html

Netty: Using SPDY and HTTP transparently

Most people have already heard about SPDY, the protocol, from google, proposed as a replacement for the aging HTTP protocol. Webservers are browsers are slowly implementing this protocol and support is growing. In a recent
article I already wrote about how SPDY works and how you can enable SPDY support in Jetty. Since a couple of months Netty (originally from JBoss) also has support for
SPDY.Since Netty is often used for high performant protocol servers, SPDY is a logical fit. In this article I’ll show you how you can create a basic Netty based server that does protocol negotiation between SPDY and HTTP. It used the example HTTPRequestHandler from the
Netty snoop example to consume and produce some HTTP content.




To get everything working we’ll need to do the following things:

  • Enable NPN in Java to determine protocol to use.
  • Determine, based on the negotiated protocol, whether to use HTTP or SPDY.
  • Make sure the correct SPDY headers are sent back with HTTP.

SPDY uses an TLS extension to determine the protocol to use in communication. This is called NPN. I wrote a more complete explanation and shown the messages involved in the article on
how to use SPDY on Jetty, so for more info look at that article. Basically what this extension does is that during the TLS exchange a server and client also exchange the transport level protocols they support. In the case of SPDY a server could support both the SPDY protocol and the HTTP protocol. A client implementation can then determine which protocol to use.

Since this isn’t something which is available in the standard Java implementation, we need to extend the Java TLS functionality with NPN.

Enable NPN support in Java

So far I found two options that can be used to add NPN support in Java. One is from
https://github.com/benmmurphy/ssl_npn who also has a basic SPDY/Netty example in his
repo where he uses his own implementation. The other option, and the one I’ll be using, is the NPN support provided by
Jetty. Jetty provides an easy to use API that you can use to add NPN support to your Java SSL contexts. Once again, in the in the article on
Jetty you can find more info on this. To set up NPN for Netty, we need to do the following:

  1. Add NPN lib to bootpath
  2. Connect the SSL context to the NPN Api

Add NPN lib to boothpath

First things first. Download the NPN boot jar from
http://repo2.maven.org/maven2/org/mortbay/jetty/npn/npn-boot/8.1.2.v2012… and make sure that when you run the server you start it like this:

java -Xbootclasspath/p:<path_to_npn_boot_jar> 

With this piece of code, Java SSL has support for NPN. We still, however, need access to the results from this negotiation. We need to know whether we’re using HTTP or SPDY, since that determines how we process the received data. For this Jetty provides an API. For this and for the required Netty libraries, we add the following dependencies, since I’m using maven, to the pom.

  <dependency>
   <groupId>io.netty</groupId>
   <artifactId>netty</artifactId>
   <version>3.4.1.Final</version>
  </dependency>
 
  <dependency>
   <groupId>org.eclipse.jetty.npn</groupId>
   <artifactId>npn-api</artifactId>
   <version>8.1.2.v20120308</version>
  </dependency>


Connect the SSL context to the NPN API

Now that we’ve got NPN enabled and the correct API added to the project, we can configure the Netty SSL handler. Configuring handlers in Netty is done in a PipelineFactory. For our server I created the following PipelineFactory:

package smartjava.netty.spdy; 
import static org.jboss.netty.channel.Channels.pipeline;
 
import java.io.FileInputStream;
import java.security.KeyStore;
 
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLEngine;
 
import org.eclipse.jetty.npn.NextProtoNego;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelPipelineFactory;
import org.jboss.netty.handler.ssl.SslHandler;
 
public class SPDYPipelineFactory implements ChannelPipelineFactory {
 
 private SSLContext context;
 
 public SPDYPipelineFactory() {
  try {
   KeyStore keystore = KeyStore.getInstance("JKS");
   keystore.load(new FileInputStream("src/main/resources/server.jks"),
     "secret".toCharArray());
 
   KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
   kmf.init(keystore, "secret".toCharArray());
 
   context = SSLContext.getInstance("TLS");
   context.init(kmf.getKeyManagers(), null, null);
 
  } catch (Exception e) {
   e.printStackTrace();
  }
 }
 
 public ChannelPipeline getPipeline() throws Exception {
  // Create a default pipeline implementation.
  ChannelPipeline pipeline = pipeline();
 
  // Uncomment the following line if you want HTTPS
  SSLEngine engine = context.createSSLEngine();
  engine.setUseClientMode(false);
 
  NextProtoNego.put(engine, new SimpleServerProvider());
  NextProtoNego.debug = true;
 
  pipeline.addLast("ssl", new SslHandler(engine));
  pipeline.addLast("pipeLineSelector", new HttpOrSpdyHandler());
 
  return pipeline;
 }
}

In the constructor from this class we setup a basic SSL context. The keystore and key we use I created using the java keytool, this is normal SSL configuration. When we receive a request, the getPipeline operation is called to determine how to handle the request. Here we use the NextProtoNego class, provided by Jetty-NPN-API, to connect our SSL connection to the NPN implementation. In this operation we pass a provider that is used as callback and configuration for our server. We also set NextProtoNego.debug to true. This prints out some debugging information that makes, well, debugging easier. The code for the SimpleServerProvider is very simple:

 public class SimpleServerProvider implements ServerProvider {
 
 private String selectedProtocol = null;
 
 public void unsupported() {
  //if unsupported, default to http/1.1
  selectedProtocol = "http/1.1";
 }
 
 public List<String> protocols() {
     return Arrays.asList("spdy/2","http/1.1");
 }
 
 public void protocolSelected(String protocol) {
  selectedProtocol = protocol;
 }
 
 public String getSelectedProtocol() { 
  return selectedProtocol;
 }
}

This code is pretty much self-explanatory.

  • The unsupported operation is called when the client doesn’t support NPN. In that case we default to HTTP.
  • The protocols() operation returns the protocols the server supports
  • The protocolSelected operation is called when a protocol has been negotiated by the server and the client

The getSelectedProtocol is a method we will use to get the selected protocol from a different handler in the Netty pipeline.

Determine, based on the negotiated protocol, whether to use HTTP or SPDY

Now we need to configure Netty in such a way that it runs a specific pipeline for HTTPS request and a pipeline for SPDY requests. For this let’s look back at a small part of the pipelinefactory.

pipeline.addLast("ssl", new SslHandler(engine));
pipeline.addLast("pipeLineSelector", new HttpOrSpdyHandler());

The first part of this pipeline is the SslHandler that is configured with NPN support. The next handler that will be called is the HttpOrSpdyHandler. This handler determines, based on the protocol, which pipeline to use. The code for this handler is listed next:

public class HttpOrSpdyHandler implements  ChannelUpstreamHandler {
 
 public void handleUpstream(ChannelHandlerContext ctx, ChannelEvent e)
   throws Exception {
 
  // determine protocol type
  SslHandler handler = ctx.getPipeline().get(SslHandler.class);
  SimpleServerProvider provider = (SimpleServerProvider) NextProtoNego.get(handler.getEngine());
 
  if ("spdy/2".equals(provider.getSelectedProtocol())) {
   ChannelPipeline pipeline = ctx.getPipeline();
 
         pipeline.addLast("decoder", new SpdyFrameDecoder());
         pipeline.addLast("spdy_encoder", new SpdyFrameEncoder());
         pipeline.addLast("spdy_session_handler", new SpdySessionHandler(true));
         pipeline.addLast("spdy_http_encoder", new SpdyHttpEncoder());
 
               // Max size of SPDY messages set to 1MB
         pipeline.addLast("spdy_http_decoder", new SpdyHttpDecoder(1024*1024)); 
         pipeline.addLast("handler", new HttpRequestHandler());
 
         // remove this handler, and process the requests as spdy
         pipeline.remove(this);
   ctx.sendUpstream(e);
  }  else if ("http/1.1".equals(provider.getSelectedProtocol())) {
   ChannelPipeline pipeline = ctx.getPipeline();
   pipeline.addLast("decoder", new HttpRequestDecoder());
   pipeline.addLast("http_encoder", new HttpResponseEncoder());
   pipeline.addLast("handler", new HttpRequestHandler());
 
   // remove this handler, and process the requests as http
   pipeline.remove(this);
   ctx.sendUpstream(e);
  } else {
   // we're still in protocol negotiation, no need for any handlers
   // at this point.
  }
 }
}

Using the NPN API and our current SSL context, we retrieve the SimpleServerProvider we added earlier. We check whether the selectedProtocol has been set, and if so, we setup a chain for processing. We handle three options in this class:

  1. There is no protocol: It’s possible that no protocol has been negotiated yet. In that case we don’t do anything special, and just process it normally.
  2. There is a http protocol: We set up a handler chain to handle HTTP requests.
  3. There is a spdy protocol: We set up a handler chain to handle SPDY requests.

With this chain all the messages we receive eventually by the HttpRequestHandler are HTTP Requests. We can process this HTTP request normally, and return a HTTP response. The various pipeline configurations will handle all this correctly.

Make sure the correct SPDY headers are sent back with HTTP

The final step we need to do, is this test. We’ll test this with the latest version of Chrome to test whether SPDY is working, and we’ll use wget to test the normal http requests. I mentioned that the HttpRequestHandler, the last handler in the chain, does our HTTP processing. I’ve used the
http://netty.io/docs/stable/xref/org/jboss/netty/example/http/snoop/Http… as the HTTPRequestHandler since that one nicely returns information about the HTTP request, without me having to do anything. If you run this without alteration, you do run into an issue. To correlate the HTTP response to the correct SPDY session, we need to copy a header from the incoming request to the response: the "X-SPDY-Stream-ID" header. I’ve added the following to the HttpSnoopServerHandler to make sure these headers are copied (should really have done this in a seperate handler).

        private final static String SPDY_STREAM_ID = = "X-SPDY-Stream-ID";
        private final static String SPDY_STREAM_PRIO = "X-SPDY-Stream-Priority";
 
        // in the writeResponse method add
 
        if (request.containsHeader(SPDY_STREAM_ID)) {
            response.addHeader(SPDY_STREAM_ID,request.getHeader(SPDY_STREAM_ID));
            // optional header for prio
            response.addHeader(SPDY_STREAM_PRIO,0);
        }

Now all that is left is a server with a main to start everything, and we can test our SPDY implementation.

public class SPDYServer {
 
 public static void main(String[] args) {
  // bootstrap is used to configure and setup the server
  ServerBootstrap bootstrap = new ServerBootstrap(
    new NioServerSocketChannelFactory(
      Executors.newCachedThreadPool(),
      Executors.newCachedThreadPool()));
 
  bootstrap.setPipelineFactory(new SPDYPipelineFactory());
  bootstrap.bind(new InetSocketAddress(8443));
 }
}

Start up the server, fire up Chrome and let’s see whether everything is working. Open the
https://localhost:8443/thisIsATest url and you should get a result that looks something like this:


In the output of the server, you can see some NPN debug logging:

[S] NPN received for 68ce4f39[SSLEngine[hostname=null port=-1] SSL_NULL_WITH_NULL_NULL]
[S] NPN protocols [spdy/2, http/1.1] sent to client for 68ce4f39[SSLEngine[hostname=null port=-1] SSL_NULL_WITH_NULL_NULL]
[S] NPN received for 4b24e48f[SSLEngine[hostname=null port=-1] SSL_NULL_WITH_NULL_NULL]
[S] NPN protocols [spdy/2, http/1.1] sent to client for 4b24e48f[SSLEngine[hostname=null port=-1] SSL_NULL_WITH_NULL_NULL]
[S] NPN selected 'spdy/2' for 4b24e48f[SSLEngine[hostname=null port=-1] SSL_NULL_WITH_NULL_NULL]

An extra check is looking at the open SPDY sessions in chrome browser by using the following url: chrome://net-internals/#spdy

Now lets check whether plain old HTTP is still working. From a command line do the following:

jos@Joss-MacBook-Pro.local:~$ wget --no-check-certificate https://localhost:8443/thisIsATest
--2012-04-27 16:29:09--  https://localhost:8443/thisIsATest
Resolving localhost... ::1, 127.0.0.1, fe80::1
Connecting to localhost|::1|:8443... connected.
WARNING: cannot verify localhost's certificate, issued by `/C=NL/ST=NB/L=Waalwijk/O=smartjava/OU=smartjava/CN=localhost':
  Self-signed certificate encountered.
HTTP request sent, awaiting response... 200 OK
Length: 285 [text/plain]
Saving to: `thisIsATest'
 
100%[==================================================================================>] 285         --.-K/s   in 0s      
 
2012-04-27 16:29:09 (136 MB/s) - `thisIsATest' saved [285/285]
 
jos@Joss-MacBook-Pro.local:~$ cat thisIsATest 
WELCOME TO THE WILD WILD WEB SERVER
===================================
VERSION: HTTP/1.1
HOSTNAME: localhost:8443
REQUEST_URI: /thisIsATest
 
HEADER: User-Agent = Wget/1.13.4 (darwin11.2.0)
HEADER: Accept = */*
HEADER: Host = localhost:8443
HEADER: Connection = Keep-Alive
 
jos@Joss-MacBook-Pro.local:~$ 

And it works! Wget uses standard HTTPS, and we get a result, and chrome uses SPDY and presents the result from the same handler. In the net couple of days, I’ll also post on article on how you can enable SPDY for the Play Framework 2.0, since their webserver is also based on Netty.


Reference:
Using SPDY and HTTP transparently using Netty from our
JCG partner Jos Dirksen at the
Smart Java blog.

Source : http://www.javacodegeeks.com/2012/05/netty-using-spdy-and-http-transparently.html

Looking for search? Find it on Google App Engine

For almost as long as we can remember, full text search has been one of the top feature requests for Google App Engine. Since our talk at Google I/O last year, we’ve been hard at work getting search ready for our developers, and today we’re happy to announce that we are making it available as an Experimental feature.



The Search API, like many other features of Google App Engine, allows you to take advantage of parts of Google’s infrastructure to add full text search to your application. This release includes a host of features including searching specific fields and ranges as well as more advanced features like scoring and snippeting. Whether you want to index products and search price ranges or just match keywords over articles and comments, the Search API is ready for you to test drive.

To help you start integrating search into your application, we’ve created a sample application and walkthrough and documented our known issues. We are extending a limited free quota for testing during our Experimental period.

As always, we’re grateful to all of our trusted testers for their patience and feedback in preparation for this launch, and we look forward to your feedback on the groups. Happy searching (and finding)!


– Posted by the Google App Engine Full Text Search Team

Source : http://googleappengine.blogspot.ca/2012/05/looking-for-search-find-it-on-google.html