Tony Printezis provided some insight into G1 in JavaOne last year. Now, we can see G1 in action with the latest JDK 6 builds. HotSpot JVM features this new collection mechanism in the recent Java SE update 14 early access builds (since b02). It is not enabled by default as this is still an experimental beta feature. But it is quite easy to enable this option for your application.

To enable it, use the JVM option:

-XX:+UnlockExperimentalVMOptions -XX:+UseG1GC

The available collectors in JDK 6 are:

1. Serial (-XX:+UseSerialGC)
2. Parallel (-XX:+UseParallelGC)
3. Concurrent (-XX:+UseConcMarkSweepGC)

Sun’s research paper explains the algorithm behind this collector. The G1 collector is meant to be an alternate for the concurrent collector for the HotSpot 14.

Java SE 6 Update 14 FCS is planned for Q2 2009. The latest available build is b03.

I did play with this new feature from b02 and my initial tests showed that it does not perform better yet than the concurrent collector. I am planning to run some more tests with b03 and will keep updated on my findings.

Possibly Related Posts:


Sergey recently implemented multipart support for CXF JAXRS implementation which is available in 2.2-SNAPSHOT. He talks more about the feature in his blog here. It certainly provides a simpler programming model like any other CXF frontends, which I always liked with the CXF project and prime reason for its growing popularity among developers. It supports multipart/related, multipart/alternative, multipart/mixed and multipart/form-data out-of-the-box. I gave it a spin and programming multiparts in CXF was like a piece of cake and you would know why by looking at the code shortly. The ability to reuse your code across SOAP and REST is the key differentiator for CXF when compared to Jersey and RESTEasy. I will leave this discussion for another blog post.

I will be reusing the same example which I used in my earlier blog entry for describing Jersey multiparts.

In this sample, I used the brand new HttpClient 4.0 API as the REST client for invoking restful services, as CXF does not ship one yet. HttpClient 4.0 API is completely redesigned and addresses most of the architectural shortcomings from its previous releases, and this version is not backwards compatible.

Here is my maven dependencies:

    <dependencies>
        <dependency>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-rt-frontend-jaxrs</artifactId>
            <version>2.2</version>
        </dependency>

        <dependency>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-rt-transports-http-jetty</artifactId>
            <version>2.2</version>
        </dependency>

        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpclient</artifactId>
            <version>4.0-beta2</version>
        </dependency>

        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpmime</artifactId>
            <version>4.0-beta2</version>
        </dependency>
    </dependencies>

Here is the Multipart resource, which processes two body parts and returns the entity with the rank set on the Project bean.

import org.apache.cxf.helpers.IOUtils;
import org.apache.cxf.io.CachedOutputStream;
import org.apache.cxf.jaxrs.ext.multipart.Attachment;
import org.apache.cxf.jaxrs.ext.multipart.MultipartBody;

import javax.activation.DataHandler;
import javax.ws.rs.*;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.MediaType;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Unmarshaller;
import java.io.InputStream;
import java.util.List;

@Path("/multipart")
public class MultipartResource {
    @POST
    @Consumes(MediaType.MULTIPART_FORM_DATA)
    @Produces(MediaType.APPLICATION_XML)
    public Response processMultiparts(MultipartBody multipartBody) {
        List<Attachment> attachments = multipartBody.getAllAttachments();
        DataHandler dataHandler1 = attachments.get(0).getDataHandler();
        DataHandler dataHandler2 = attachments.get(1).getDataHandler();
        Project project = null;
        try {
            project = getProjectFromInputStream(dataHandler1.getInputStream());
            System.out.println("Processing Attachment 1 ...");
            System.out.println("name : " + project.getName());
            System.out.println("description : " + project.getDescription());
            System.out.println("license : " + project.getLicense());
            System.out.println("SVN URL : " + project.getSvnURL());
            System.out.println("homepage : " + project.getHomepage());

            System.out.println("Processing Attachment 2 ...");
            String comment = getStringFromInputStream(dataHandler2.getInputStream());
            System.out.println("Comment : " + comment);

        } catch (Exception e) {
            throw new WebApplicationException(500);
        }
        return Response.ok(project).build();
    }

    public static Project getProjectFromInputStream(InputStream is) throws Exception {
        JAXBContext c = JAXBContext.newInstance(new Class[]{Project.class});
        Unmarshaller u = c.createUnmarshaller();
        Project project = (Project) u.unmarshal(is);
        project.setRank(1);
        return project;
    }

    public static String getStringFromInputStream(InputStream in) throws Exception {
        CachedOutputStream bos = new CachedOutputStream();
        IOUtils.copy(in, bos);
        in.close();
        bos.close();
        return bos.getOut().toString();
    }

}

Start the Jetty based CXF JAXRS server which deploys the multipart resource as a singleton.

public class CXFRestServer {
    public static void main(String[] args) {
        JAXRSServerFactoryBean sf = new JAXRSServerFactoryBean();
        sf.setResourceClasses(MultipartResource.class);
        sf.setResourceProvider(MultipartResource.class,
                new SingletonResourceProvider(new MultipartResource()));
        sf.setAddress("http://localhost:8081/");
        sf.create();
        System.out.println("Server started.");
    }
}

HttpClient APIs are used to POST the multipart entites to the CXF multipart resource. The first part is a XML File and the second part is a String content. Finally, it processes the response received from the resource.

public class TestClient {

    public static void main(String[] args) throws Exception {
        HttpClient httpclient = new DefaultHttpClient();
        HttpPost httppost = new HttpPost("http://localhost:8081/multipart");
        FileBody bin = new FileBody(new File(TestClient.class.getResource("/project_summary.xml").getFile()));
        StringBody comment = new StringBody("Project summary.");

        MultipartEntity reqEntity = new MultipartEntity();
        reqEntity.addPart("project", bin);
        reqEntity.addPart("comment", comment);

        httppost.setEntity(reqEntity);

        System.out.println("executing request " + httppost.getRequestLine());
        HttpResponse response = httpclient.execute(httppost);
        HttpEntity resEntity = response.getEntity();

        System.out.println("---------------------------------------------------------------");
        System.out.println(response.getStatusLine());
        if (resEntity != null) {
            System.out.println("Response content length: " + resEntity.getContentLength());
            System.out.println("Response content type: " + resEntity.getContentType().getValue());
            System.out.println("Project Rank : " + MultipartResource.getProjectFromInputStream(resEntity.getContent()).getRank());
        }
        if (resEntity != null) {            
            resEntity.consumeContent();
        }
    }
}

Place project_summary.xml in your root classpath.

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<project>
    <name>CXF</name>
    <description>Apache CXF is an open source services framework.</description>
    <homepage>http://cxf.apache.org</homepage>
    <license>ASL 2.0</license>
    <svnURL>http://svn.apache.org/repos/asf/cxf/trunk/</svnURL>
</project>

This is just one approach of doing multiparts with CXF JAXRS implementation. You can dig into the unit tests to see all possible approaches to handle multiparts with in restful resources. HttpClient 4.0 API is cleaner and flexible and could potentially become a standard API for accessing RESTful web services in Java.

Update (4/11): The sample is updated to use the 2.2 release. The sources can be downloaded from here.

Possibly Related Posts:


Support for 64-bit Java plug-in finally available with Update 12 early access. This feature request was a 4 year old RFE in Sun’s bug database. I just installed this plug-in on my 64-bit vista. Its nice to see your 64-bit browsers verify Java by clicking here. Sun is planning to open source Java Web Start implementation and the new plug-in implementation for NPAPI capable browsers as mentioned by Joe Darcy here. Yet another step in making free and open Java platform for everyone. Kudos to Sun.

I noticed one thing when installing this early access release, it bundles MSN toolbar. I did not notice if this was the case with earlier updates.

Java SE 6 Update 12 EA snapshot

Hate to see these kind of promos in Java installer 🙁

Possibly Related Posts:


LoanDB is a loan originations system reference implementation. This project will be developed using Java technology frameworks such as Spring (Web Beans in future?), Hibernate (JPA), CXF (JAXWS) and Jersey (JAXRS). The concepts are based on my original toy implementation for the loan processing NetBeans tutorial. The tutorial was primarily focused on developing JPA and web services based applications in NetBeans IDE, so you won’t find the real meat. I am thinking of designing various modules around the LoanDB core and I am expecting this to be more useful for Java developers in understanding how these frameworks help in solving traditional enterprise application integration problems and further help in developing less maintainable code, which is rather more critical in enterprises. Loan Originations system is a very good candidate for implementing SOA based solution and typically involves integration with many heterogeneous systems within network and outside the network. This is going to be real fun developing this project.

I plan to blog more about the frameworks used in this project shortly. Currently, I am in the process of designing the persistence layer, which is the core of this project. Some prototype code out there in SVN. But remember, right now there are too many moving parts before I flush out something concrete, so I have no release plans yet 🙂

Possibly Related Posts:


Multipart API in Jersey was made available by Craig in the recent 1.0.1 release. This API provides a simple mechanism to read and write body parts from within a restful application. Lets walk through a simple project resource which processes two parts, one JAXB bean and other an image.

Add the following jersey maven dependencies for running this sample.

        <dependency>
            <groupId>com.sun.jersey</groupId>
            <artifactId>jersey-server</artifactId>
            <version>1.0.1</version>
        </dependency>

        <dependency>
            <groupId>com.sun.jersey</groupId>
            <artifactId>jersey-client</artifactId>
            <version>1.0.1</version>
        </dependency>

        <dependency>
            <groupId>com.sun.jersey.contribs</groupId>
            <artifactId>jersey-multipart</artifactId>
            <version>1.0.1</version>
        </dependency>

        <dependency>
            <groupId>com.sun.grizzly</groupId>
            <artifactId>grizzly-servlet-webserver</artifactId>
            <version>1.9.0</version>
            <scope>test</scope>
        </dependency>

ProjectResource is fairly straight forward. It receives the body parts and processes them. Stores the image in file system. This resource consumes “multipart/mixed” type as there can be body parts with different media types sent in the multipart.

import com.sun.jersey.multipart.BodyPartEntity;
import com.sun.jersey.multipart.MultiPart;
import jersey.multipart.demo.model.Project;

import javax.imageio.ImageIO;
import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.InputStream;
import java.util.UUID;

@Path("/project")
public class ProjectResource {


  @POST
  @Consumes("multipart/mixed")
  public Response post(MultiPart multiPart) {
    // First part contains a Project object
    Project project = multiPart.getBodyParts().get(0).getEntityAs(Project.class);
    System.out.println("name : " + project.getName());
    System.out.println("description : " + project.getDescription());
    System.out.println("license : " + project.getLicense());
    System.out.println("SVN URL : " + project.getSvnURL());
    System.out.println("homepage : " + project.getHomepage());

    // get the second part which is the project logo
    BodyPartEntity bpe = (BodyPartEntity) multiPart.getBodyParts().get(1).getEntity();
    String id = UUID.randomUUID().toString();
    boolean isProcessed = false;
    String message = null;
    try {
      InputStream source = bpe.getInputStream();
      BufferedImage bi = ImageIO.read(source);

      File file = new File(".\\\received\\\" + id + ".png");

      //storing the image to file system.
      if (file.isDirectory()) {
        ImageIO.write(bi, "png", file);
      } else {
        file.mkdirs();
        ImageIO.write(bi, "png", file);
      }
      isProcessed = true;

    } catch (Exception e) {
      message = e.getMessage();
    }
    if (isProcessed) {
      return Response.status(Response.Status.ACCEPTED).entity("Attachements processed successfully.").type(MediaType.TEXT_PLAIN).build();
    }

    return Response.status(Response.Status.BAD_REQUEST).entity("Failed to process attachments. Reason : " + message).type(MediaType.TEXT_PLAIN).build();
  }

}

The client code is simple enough. The multipart is a collection of body parts and it each body part should be associated with its media type. In our case, the first part is of “application/xml” since its a JAXB bean and the second part is of type “application/octet-stream” which is a PNG image. After constructing the multipart, you can post the data to the JAX-RS resource using the Jersey client API.

import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.WebResource;
import com.sun.jersey.multipart.BodyPart;
import com.sun.jersey.multipart.MultiPart;
import jersey.multipart.demo.model.Project;

import javax.imageio.ImageIO;
import javax.ws.rs.core.MediaType;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.net.URL;

public class ProjectClient {
  public static void main(String[] args) throws Exception {
    final String BASE_URI = "http://localhost:9998/";

    Client c = Client.create();
    WebResource service = c.resource(BASE_URI);

    Project project = new Project();
    project.setName("Jersey");
    project.setDescription("Jersey is the open source, production quality, JAX-RS (JSR 311) Reference Implementation for building RESTful Web services.");
    project.setHomepage("https://jersey.dev.java.net/");
    project.setLicense("dual CDDL+GPL license");
    project.setSvnURL("https://jersey.dev.java.net/svn/jersey/trunk");

    ByteArrayOutputStream bas = new ByteArrayOutputStream();
    URL url = new URL("https://jersey.dev.java.net/images/Jersey_yellow.png");
    BufferedImage bi = ImageIO.read(url);
    ImageIO.write(bi, "png", bas);
    byte[] logo = bas.toByteArray();

    // Construct a MultiPart with two body parts
    MultiPart multiPart = new MultiPart().
      bodyPart(new BodyPart(project, MediaType.APPLICATION_XML_TYPE)).
      bodyPart(new BodyPart(logo, MediaType.APPLICATION_OCTET_STREAM_TYPE));

    // POST the request
    ClientResponse response = service.path("/project").
      type("multipart/mixed").post(ClientResponse.class, multiPart);
    System.out.println("Response Status : " + response.getEntity(String.class));
  }
}

The server code uses Grizzly container to deploy the Jersey resource and it enables easier testing. Make sure the grizzly project dependency is added to the POM in order to run this code.

import com.sun.grizzly.http.SelectorThread;
import com.sun.jersey.api.container.grizzly.GrizzlyWebContainerFactory;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

public class Server {
  public static void main(String[] args) throws IOException {
    final String baseUri = "http://localhost:9998/";
    final Map<String, String> initParams = new HashMap<String, String>();
    initParams.put("com.sun.jersey.config.property.packages",
      "jersey.multipart.demo.resources");
    System.out.println("Starting grizzly...");
    SelectorThread threadSelector = GrizzlyWebContainerFactory.create(baseUri, initParams);
    System.out.println(String.format("Jersey app started with WADL available at %sapplication.wadl\n"
      + "Try out %sproject\nHit enter to stop it...", baseUri, baseUri));
    System.in.read();
    threadSelector.stopEndpoint();
    System.exit(0);
  }
}

Handling multiparts in restful resources comes handy for certain web applications and Jersey provides this neat piece of integration as part of the JAX-RS RI.

Jersey rocks 🙂

Possibly Related Posts:


Spring Framework 3.0 M1 was released last week during the SpringOne Americas event, which looks very promising with EL and REST becoming top themes. Lot of coverage on the event has been blogged, and you can find one of my favorite entry by Solomon here. Juergen outlines some of the new features implemented in this milestone release here.

SVN repository for Spring Framework 3.0 is hosted by SpringSource at https://src.springframework.org/svn/spring-framework/trunk.
The build requires JDK 6, but Spring Framework 3.0 requires Java 5 or above. Not sure how this would work when building with a later Java version.

Other interesting note is that some parts of Spring JavaConfig will be merged with Spring Core. SJC is really powerful and you can almost do everything XML configuration can do. It would be nice to see both XML and Java configuration part of the core framework.

Possibly Related Posts:


Jersey Today, Paul announced in his blog about the availability of Jersey 1.0. I have been waiting for this release like many others. The Jersey team delivered a pretty solid implementation and this implementation has been tested by the user community to a greater extent. This project can be considered as a blueprint for similar JSR implementations. Feedbacks were incorporated and the team was very responsive to user community and you can see more users using Jersey than any other JAX-RS implementations (RESTEasy, Restlet, Apache CXF). Jersey is considered to be more stable than its counterpart as it fully conforms to the JSR311 API and has support for Spring and houses a Jersey Client modeled around the resource concept. NetBeans 6.5 Beta has a decent tooling support for JAX-RS using Jersey.

Kudos to team Jersey!

Possibly Related Posts:


Yahoo Search provides a RESTful interface for web search. Of course this service is been there for a while. I was just curious to use Jersey Client to play around with the Yahoo REST service. It opens up a world of possibilities for building applications around these services in Java.

Let us invoke the web search API using GET and context search API using POST as described in the following URLs.

http://search.yahooapis.com/WebSearchService/V1/webSearch?appid=YahooDemo&query=finances&format=pdf (GET)

http://search.yahooapis.com/WebSearchService/V1/contextSearch (POST)
appid=YahooDemo&query=madonna&context=Italian+sculptors+and+painters+of+the+renaissance+favored+the+Virgin+Mary+for+inspiration

The URL is constructed using the actual query parameters for accessing web resources which takes the URL encoded “argument=value” form.

The below code shows how we can quickly write a Jersey based REST client for invoking these RESTful web services. The APIs are fairly self-explanatory.

import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.WebResource;
import com.sun.jersey.api.representation.Form;
import restful.search.jaxb.ResultSet;
import restful.search.jaxb.ResultType;

import javax.ws.rs.core.MediaType;

public class YahooRestfulSearchClient {
    public static void main(String args[]) {
        Client client = Client.create();
        WebResource r = client.resource("http://search.yahooapis.com/WebSearchService/V1/webSearch?appid=YahooDemo&query=finances&format=pdf");
        ResultSet searchResults = r.accept(MediaType.APPLICATION_XML).get(ResultSet.class);
        for (ResultType result : searchResults.getResult()) {
            System.out.println("Title : " + result.getTitle());
            System.out.println("Summary : " + result.getSummary());
            System.out.println("Url : " + result.getUrl());
        }

        Form form = new Form();
        form.add("appid", "YahooDemo");
        form.add("query", "madonna");
        form.add("context", "Italian sculptors and painters of the renaissance favored the Virgin Mary for inspiration");

        r = client.resource("http://search.yahooapis.com/WebSearchService/V1/contextSearch");
        searchResults = r.accept(MediaType.APPLICATION_XML).post(ResultSet.class, form);        
        for (ResultType result : searchResults.getResult()) {
            System.out.println("Title : " + result.getTitle());
            System.out.println("Summary : " + result.getSummary());
            System.out.println("Url : " + result.getUrl());
        }        
    }
}

I updated my original approach for invoking the Context search based on the suggestions from Jersey developers to use Jersey form parameters encoded in the body of the request instead of directly constructing the URI as a request entity in the post call. Typically, POST is used to create web resources. But, Yahoo documentation suggests that POST be used for context searches just because the query params can sometimes be potentially lengthy, and hence the recommendation to send query parameters in the POST data block. The other option in Jersey is to use the UriBuilder to construct the URI and add query parameters to the URI. The code snip below shows this latter approach. Using form parameters is more elegant than constructing lengthy URIs 🙂


        URI uri = UriBuilder.fromPath("http://search.yahooapis.com/WebSearchService/V1/contextSearch").queryParam("appid", "YahooDemo").queryParam("query", "madonna").queryParam("context", "Italian sculptors and painters of the renaissance favored the Virgin Mary for inspiration").build();
        r = client.resource(uri);
        searchResults = r.accept(MediaType.APPLICATION_XML).post(ResultSet.class);

In both these approaches, the crux lies in the response type ‘ResultSet’ which is described in the below schema for the responses returned from the Yahoo REST service. You can access the schema here. Here is a quick look at the schema.

<?xml version="1.0" encoding="utf-8" ?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
  targetNamespace="urn:yahoo:srch"
  xmlns="urn:yahoo:srch"
  elementFormDefault="qualified">

	<xs:element name="ResultSet">
		<xs:complexType>
			<xs:sequence>
				<xs:element name="Result" type="ResultType" minOccurs="0" maxOccurs="100" />
			</xs:sequence>
			<xs:attribute name="totalResultsAvailable" type="xs:integer" />
			<xs:attribute name="totalResultsReturned" type="xs:integer" />

			<xs:attribute name="firstResultPosition" type="xs:integer" />
		</xs:complexType>
	</xs:element>

	<xs:complexType name="ResultType">
		<xs:sequence>
			<xs:element name="Title" type="xs:string" />
			<xs:element name="Summary" type="xs:string" />
			<xs:element name="Url" type="xs:string" />

			<xs:element name="ClickUrl" type="xs:string" />
			<xs:element name="ModificationDate" type="xs:string" minOccurs="0" />
			<xs:element name="MimeType" type="xs:string" minOccurs="0" />
			<xs:element name="Cache" type="CacheType" minOccurs="0" />
		</xs:sequence>
	</xs:complexType>

	<xs:complexType name="CacheType">
		<xs:sequence>
			<xs:element name="Url" type="xs:string" />

			<xs:element name="Size" type="xs:string" />
		</xs:sequence>
	</xs:complexType>

</xs:schema>

Use this schema to generate your JAXB types (ResultSet, ResultType, CacheType) and you are ready to consume the response within your REST client. The best part of this exercise was using IntelliJ IDEA 8.0M1. This latest release has support for REST client plugin where you can test your restful resources and it supports RESTful development using Jersey. More to explore on this front. Here is a screen shot of IDEA8 Rest Client in action.
IDEA8 Rest Client

Possibly Related Posts:


It has been a wonderful week with my ramblings with CXF and SSL. But, it all ended up in good mood. Sometimes, it is so hard to find how to use certain features with CXF. I am a great fan of CXF because of its simplicity and intuitive feature set. It provides an array of integration points with best of breed technologies, but sadly most of the crux is buried under its system tests or CXF user mailing list archive. The documentation front is really lacking its meat from the “source”. So, people end up debugging CXF which is the only weapon to invade your configuration issues.

The community around CXF is very healthy and gained substantial momentum in all fronts for the past year or so. CXF user mailing list is such an awful resource. Its the first resort to get your queries answered and if you don’t get a response, don’t wait, just debug yourself. The resources are very limited and their support is really appreciated.

I wanted to contribute a sample for programmatic setup of SSL with CXF using embedded Jetty, so people get it right at the first time. So, I ported the sample “wsdl_first_https” which is bundled with CXF 2.1.1 distribution to a “java_first_https” scenario. The “wsdl_first_https” sample uses Spring based configuration for SSL. Though this scenario seem to fit well where the application uses spring as its underlying DI framework. For people who wish not to care about Spring, why would they want to unnecessarily bundle Spring jars for achieving CXF/SSL support in their application. But, this all depends on what approach you chose to build your services with CXF (either using Spring config or Java APIs). This is just a simple case for building this demo in “no-Spring” way. It opens a whole world of possibilities for dynamically configuring security in your embedded Jetty container.

Lets take the simple Greeter service which greets the client with its name sent as an input parameter.

@WebService
public interface Greeter {

    String greetMe(String me);
}


@javax.jws.WebService(name = "Greeter", serviceName = "SOAPService",
                      targetNamespace = "http://apache.org/hello_world_soap_http")
public class GreeterImpl implements Greeter {
    private static final Logger LOG =
        Logger.getLogger(GreeterImpl.class.getPackage().getName());

    public String greetMe(String me) {
        LOG.info("Executing operation greetMe");
        System.out.println("Executing operation greetMe");
        System.out.println("Message received: " + me + "\n");
        return "Hello " + me;
    }
}

The demo uses the same client and server certificate stores shipped with “wsdl_first_https” demo in CXF 2.1.1. So, don’t forget to include them when running this demo.

The Server side SSL configuration using CXF Java APIs is shown below.

public class Server {

    protected Server() throws Exception {
        System.out.println("Starting Server");
        String address = "https://localhost:9001/SoapContext/SoapPort";
        JaxWsServerFactoryBean sf = new JaxWsServerFactoryBean();
        sf.setServiceClass(Greeter.class);
        sf.setAddress(address);

        Greeter implementor = new GreeterImpl();
        sf.getServiceFactory().setInvoker(new BeanInvoker(implementor));

        sf = configureSSLOnTheServer(sf, 9001);
        org.apache.cxf.endpoint.Server server = sf.create();
        String endpoint = server.getEndpoint().getEndpointInfo().getAddress();
        
        System.out.println("Server started at " + endpoint);
    }

    private JaxWsServerFactoryBean configureSSLOnTheServer(JaxWsServerFactoryBean sf, int port) {
        try {
            TLSServerParameters tlsParams = new TLSServerParameters();
            KeyStore keyStore = KeyStore.getInstance("JKS");
            String password = "password";
            File truststore = new File("certs\\cherry.jks");
            keyStore.load(new FileInputStream(truststore), password.toCharArray());
            KeyManagerFactory keyFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
            keyFactory.init(keyStore, password.toCharArray());
            KeyManager[] km = keyFactory.getKeyManagers();
            tlsParams.setKeyManagers(km);

            truststore = new File("certs\\truststore.jks");
            keyStore.load(new FileInputStream(truststore), password.toCharArray());
            TrustManagerFactory trustFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
            trustFactory.init(keyStore);
            TrustManager[] tm = trustFactory.getTrustManagers();
            tlsParams.setTrustManagers(tm);
            FiltersType filter = new FiltersType();
            filter.getInclude().add(".*_EXPORT_.*");
            filter.getInclude().add(".*_EXPORT1024_.*");
            filter.getInclude().add(".*_WITH_DES_.*");
            filter.getInclude().add(".*_WITH_NULL_.*");
            filter.getExclude().add(".*_DH_anon_.*");
            tlsParams.setCipherSuitesFilter(filter);
            ClientAuthentication ca = new ClientAuthentication();
            ca.setRequired(true);
            ca.setWant(true);
            tlsParams.setClientAuthentication(ca);
            JettyHTTPServerEngineFactory factory = new JettyHTTPServerEngineFactory();
            factory.setTLSServerParametersForPort(port, tlsParams);
        } catch (KeyStoreException kse) {
            System.out.println("Security configuration failed with the following: " + kse.getCause());
        } catch (NoSuchAlgorithmException nsa) {
            System.out.println("Security configuration failed with the following: " + nsa.getCause());
        } catch (FileNotFoundException fnfe) {
            System.out.println("Security configuration failed with the following: " + fnfe.getCause());
        } catch (UnrecoverableKeyException uke) {
            System.out.println("Security configuration failed with the following: " + uke.getCause());
        } catch (CertificateException ce) {
            System.out.println("Security configuration failed with the following: " + ce.getCause());
        } catch (GeneralSecurityException gse) {
            System.out.println("Security configuration failed with the following: " + gse.getCause());
        } catch (IOException ioe) {
            System.out.println("Security configuration failed with the following: " + ioe.getCause());
        }

        return sf;
    }

    public static void main(String args[]) throws Exception {
        System.out.println("The server's security configuration will be done programatically.");
        System.out.println();
        new Server();
        System.out.println("Server ready...");

        Thread.sleep(5 * 60 * 1000);
        System.out.println("Server exiting");
        System.exit(0);
    }
}

The SSL server configuration using Java APIs exactly maps to spring config “CherryServer.cxf” used in the distribution.

<?xml version="1.0" encoding="UTF-8"?>
<!-- 
  ** This file configures the Cherry Server.
 -->

<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:sec="http://cxf.apache.org/configuration/security"
  xmlns:http="http://cxf.apache.org/transports/http/configuration"
  xmlns:httpj="http://cxf.apache.org/transports/http-jetty/configuration"
  xmlns:jaxws="http://java.sun.com/xml/ns/jaxws"
  xsi:schemaLocation="
       http://cxf.apache.org/configuration/security  		      http://cxf.apache.org/schemas/configuration/security.xsd
            http://cxf.apache.org/transports/http/configuration
            http://cxf.apache.org/schemas/configuration/http-conf.xsd
            http://cxf.apache.org/transports/http-jetty/configuration
            http://cxf.apache.org/schemas/configuration/http-jetty.xsd
            http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">

  <http:destination name="{http://apache.org/hello_world_soap_http}GreeterPort.http-destination"> 
  </http:destination>

  <httpj:engine-factory>
   <httpj:engine port="9001">
    <httpj:tlsServerParameters>
      <sec:keyManagers keyPassword="password">
           <sec:keyStore type="JKS" password="password" 
                file="certs/cherry.jks"/>
      </sec:keyManagers>
      <sec:trustManagers>
          <sec:keyStore type="JKS" password="password"
               file="certs/truststore.jks"/>
      </sec:trustManagers>
      <sec:cipherSuitesFilter>
        <!-- these filters ensure that a ciphersuite with
          export-suitable or null encryption is used,
          but exclude anonymous Diffie-Hellman key change as
          this is vulnerable to man-in-the-middle attacks -->
        <sec:include>.*_EXPORT_.*</sec:include>
        <sec:include>.*_EXPORT1024_.*</sec:include>
        <sec:include>.*_WITH_DES_.*</sec:include>
        <sec:include>.*_WITH_NULL_.*</sec:include>
        <sec:exclude>.*_DH_anon_.*</sec:exclude>
      </sec:cipherSuitesFilter>
      <sec:clientAuthentication want="true" required="true"/>
    </httpj:tlsServerParameters>
   </httpj:engine>
  </httpj:engine-factory>
</beans>

The Client side SSL configuration using CXF Java APIs is shown below.

public class Client {

    private static void configureSSLOnTheClient(Object c) {
        org.apache.cxf.endpoint.Client client = ClientProxy.getClient(c);
        HTTPConduit httpConduit = (HTTPConduit) client.getConduit();

        try {
            TLSClientParameters tlsParams = new TLSClientParameters();
            tlsParams.setDisableCNCheck(true);

            KeyStore keyStore = KeyStore.getInstance("JKS");
            String trustpass = "password";

            File truststore = new File("certs\\truststore.jks");
            keyStore.load(new FileInputStream(truststore), trustpass.toCharArray());
            TrustManagerFactory trustFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
            trustFactory.init(keyStore);
            TrustManager[] tm = trustFactory.getTrustManagers();
            tlsParams.setTrustManagers(tm);

            truststore = new File("certs\\wibble.jks");
            keyStore.load(new FileInputStream(truststore), trustpass.toCharArray());
            KeyManagerFactory keyFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
            keyFactory.init(keyStore, trustpass.toCharArray());
            KeyManager[] km = keyFactory.getKeyManagers();
            tlsParams.setKeyManagers(km);

            FiltersType filter = new FiltersType();
            filter.getInclude().add(".*_EXPORT_.*");
            filter.getInclude().add(".*_EXPORT1024_.*");
            filter.getInclude().add(".*_WITH_DES_.*");
            filter.getInclude().add(".*_WITH_NULL_.*");
            filter.getExclude().add(".*_DH_anon_.*");
            tlsParams.setCipherSuitesFilter(filter);

            httpConduit.setTlsClientParameters(tlsParams);
        } catch (KeyStoreException kse) {
            System.out.println("Security configuration failed with the following: " + kse.getCause());
        } catch (NoSuchAlgorithmException nsa) {
            System.out.println("Security configuration failed with the following: " + nsa.getCause());
        } catch (FileNotFoundException fnfe) {
            System.out.println("Security configuration failed with the following: " + fnfe.getCause());
        } catch (UnrecoverableKeyException uke) {
            System.out.println("Security configuration failed with the following: " + uke.getCause());
        } catch (CertificateException ce) {
            System.out.println("Security configuration failed with the following: " + ce.getCause());
        } catch (GeneralSecurityException gse) {
            System.out.println("Security configuration failed with the following: " + gse.getCause());
        } catch (IOException ioe) {
            System.out.println("Security configuration failed with the following: " + ioe.getCause());
        }
    }

    public static void main(String args[]) {
        System.out.println("The client's security configuration will be done programatically.");
        System.out.println();
        String address = "https://localhost:9001/SoapContext/SoapPort";
        JaxWsProxyFactoryBean proxyFactory = new JaxWsProxyFactoryBean();
        proxyFactory.setServiceClass(Greeter.class);
        proxyFactory.setAddress(address);

        Greeter client = (Greeter) proxyFactory.create();
        configureSSLOnTheClient(client);

        System.out.println("Invoking greetMe...");
        try {
            String resp = client.greetMe(System.getProperty("user.name"));
            System.out.println("Server responded with: " + resp);
            System.out.println();

        } catch (Exception e) {
            System.out.println("Invocation failed with the following: " + e.getCause());
            System.out.println();
        }

    }
}

The SSL client configuration using Java APIs exactly maps to spring config “WibbleClient.cxf” used in the distribution.

<?xml version="1.0" encoding="UTF-8"?>
<!-- 
  ** This file configures the Wibble Client
  -->

<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:sec="http://cxf.apache.org/configuration/security"
  xmlns:http="http://cxf.apache.org/transports/http/configuration"
  xmlns:jaxws="http://java.sun.com/xml/ns/jaxws"
  xsi:schemaLocation="
           http://cxf.apache.org/configuration/security
           http://cxf.apache.org/schemas/configuration/security.xsd
           http://cxf.apache.org/transports/http/configuration
           http://cxf.apache.org/schemas/configuration/http-conf.xsd
           http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans.xsd">

  <http:conduit name="{http://apache.org/hello_world_soap_http}SoapPort.http-conduit">
    <http:tlsClientParameters disableCNCheck="true">
      <sec:trustManagers>
          <sec:keyStore type="JKS" password="password"
               file="certs/truststore.jks"/>
      </sec:trustManagers>
      <sec:keyManagers keyPassword="password">
           <sec:keyStore type="JKS" password="password" 
                file="certs/wibble.jks"/>
      </sec:keyManagers>
      <sec:cipherSuitesFilter>
        <!-- these filters ensure that a ciphersuite with
          export-suitable or null encryption is used,
          but exclude anonymous Diffie-Hellman key change as
          this is vulnerable to man-in-the-middle attacks -->
        <sec:include>.*_EXPORT_.*</sec:include>
        <sec:include>.*_EXPORT1024_.*</sec:include>
        <sec:include>.*_WITH_DES_.*</sec:include>
        <sec:include>.*_WITH_NULL_.*</sec:include>
        <sec:exclude>.*_DH_anon_.*</sec:exclude>
      </sec:cipherSuitesFilter>
    </http:tlsClientParameters>
   </http:conduit>
</beans> 

You can download the NetBeans project here.

Possibly Related Posts:


For those who missed JavaOne this year, Sun has published the conference slides here a month later. I find these very useful especially for Java geeks as it provides an opportunity to learn some of the technical advancements around the Java platform and the momentum around the technology is healthy.

My top contenders this year were:
Building SOA Applications with JAX-WS, JAXRS, JAXB, and Ajax by Mark Hansen
Let’s Resync Concurrency Features in JDK™ 7 by Brian Goetz
Defective Java™ Code: Turning WTF code into a learning experience by William Pugh
More Effective Java by Joshua Bloch
Design Patterns Reconsidered by Alex Miller
JAX-RS: The Java™ API for RESTful Web Services by Marc Hadley and Paul Sandoz
Top 10 Patterns for Scaling Out Java™ Applications by Cameron Purdy
Groovy and Grails: Changing the Landscape of Java™ Platform, Enterprise Edition (Java EE Platform) Patterns by Graeme Rocher
Choosing a Java Web Framework: A Comparison by Richard Pack
Java™ Servlet 3.0 API: What’s new and exciting by Rajiv Mordani

Possibly Related Posts: