Wednesday, October 29, 2014

How to setup custom SSLSocketFactory's TrustManager per each URL connection

We can see from javadoc that javax.net.ssl.HttpsURLConnection provided a static method to override with setDefaultSSLSocketFory() method. This allow you to supply a custom javax.net.ssl.TrustManager that may verify your own  CA certs handshake and validation etc. But this will override the default for all "https" URLs per your JVM!

So how can we override just a single https URL? Looking at javax.net.ssl.HttpsURLConnection again we see instance method for setSSLSocketFactory(), but we can't instantiate HttpsURLConnection object directly! It took me some digging to realized that the java.net.URL is actually an factory class for its implementation! One can get an instance like this using new URL("https://localhost").openConnection()

To complete this article, I will provide a simple working example that demonstrate this.

package zemian;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;
import java.security.SecureRandom;
import java.security.cert.X509Certificate;

import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

public class WGetText {
    public static void main(String[] args) throws Exception {
        String urlString = System.getProperty("url", "https://google.com");
        URL url = new URL(urlString);
        URLConnection urlConnection = url.openConnection();
        HttpsURLConnection httpsUrlConnection = (HttpsURLConnection) urlConnection;
        SSLSocketFactory sslSocketFactory = createSslSocketFactory();
        httpsUrlConnection.setSSLSocketFactory(sslSocketFactory);
        try (InputStream inputStream = httpsUrlConnection.getInputStream()) {
            BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
            String line = null;
            while ((line = reader.readLine()) != null) {
                System.out.println(line);
            }
        }
    }

    private static SSLSocketFactory createSslSocketFactory() throws Exception {
        TrustManager[] byPassTrustManagers = new TrustManager[] { new X509TrustManager() {
            public X509Certificate[] getAcceptedIssuers() {
                return new X509Certificate[0];
            }

            public void checkClientTrusted(X509Certificate[] chain, String authType) {
            }

            public void checkServerTrusted(X509Certificate[] chain, String authType) {
            }
        } };
        SSLContext sslContext = SSLContext.getInstance("TLS");
        sslContext.init(null, byPassTrustManagers, new SecureRandom());
        return sslContext.getSocketFactory();
    }
}

Monday, October 27, 2014

How Servlet and JSP create sessions

In Servlet, you may get the Session object by "httpServletRequest.getSession(true)". The "true" flag will create the session if it doesn't already exist, else it gets the existing session.

Now if you want to check whether you have the session exists or not (without have to create one if doesn't exist), you need to pass in "false" and then check for "null".

Session session = httpServletRequest.getSession(false);
if (session == null) {
  // do something without creating session object.
}

Now comes the trick party. If you run above code and then dispatch the request to render a JSP page, you might quickly come to find out that the container will create a new Session object still! It turns out that by default JSP will create new Session object if you do not have one! To disable this, you need to set this explicitly on top of the JSP page:

 <% page session="false" %>

Only with this you will able to actually prevent creation of unnecessary Session object if you were to use JSP for output! Something to watch out for when debugging session based application.

Saturday, October 18, 2014

Poking around your REST application with a scriptable endpoint

I love the fact that JDK comes with a ScriptEngine. It's so flexible when you want to evaluate and troubleshoot your application that's already deployed in an server environment. Add this REST endpoint into a Java EE app, and it will give you instant access to internal states of the app.

package myrestapp;

import java.io.StringReader;
import java.util.logging.Logger;
import javax.script.Bindings;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.core.Context;

/**
 * Give instant access to your internal application with dynamic scripting.
 *
 * <p>Example script:
 * <pre>
 * "sc" + servletContext + ", req=" + request;
 * </pre>
 *
 * <p>Example2
 * <pre>
 * names = servletContext.getAttributeNames();
 * while(names.hasMoreElements()) {
 *   name = names.nextElement();
 *   println(name);
 * }
 * </pre>
 */
@Path("script")
public class ScriptResource {
    private static final Logger logger = Logger.getLogger(ScriptResource.class.getName());
   
    @Context
    private ServletContext servletContext;
       
    @POST
    public String script(@Context HttpServletRequest request, String scriptText) throws Exception {
        String engineName = "JavaScript";
        ScriptEngineManager manager = new ScriptEngineManager();
        ScriptEngine engine = manager.getEngineByName(engineName);
        logger.info("Running script text length=" + scriptText.length() + ", engine=" + engine);
        Object result = null;
        try (StringReader reader = new StringReader(scriptText)) {
            Bindings bindings = engine.createBindings();
            bindings.put("servletContext", servletContext);
            bindings.put("request", request);
            result = engine.eval(reader, bindings);
        }
        logger.info("Result " + result);
        return "" + result;
    }
}


Notice that I gave couple JavaScript examples in the comment area already. You will have access to two binding variables that should give you full access to many internal components of your application. And here is a quick reference on scripting JDK 7.

Need an UI to test out this endpoint? How about give the "Advance Rest Client" Chrome Extension a try? (Thanks to my co-worker's Chris Griffith for showing me this cool extension. It's really handy tool to have!).

Sunday, September 14, 2014

Book Review: Apache Camel Developer's Cookbook


I got a chance to review the "Apache CamelDeveloper's Cookbook" by Cranton and Korab. Overall I think this is a great book. System integration problems and solutions come in many forms, so getting started by reading on some proven solution recipes is definitely a good way to improve your skill. This book provides more than 100 examples on how to solve integration problems with Camel framework; from simple standalone Java application to testing, transaction, monitoring and even a chapter on web services. Each example comes with brief explanations and further reading references. My favorites are the side notes sprinkled throughout each recipe. Clearly these great tips can only have came from well experienced Camel developers who has spent time on the field.

As many cookbook style, the book can only go to certain length with each example on explanation and teaching, but readers may dig much deeper by using the sample code provided by this book. In fact I think it's really cool that it's available through GitHub as well. Check it out at http://github.com/CamelCookbook/camel-cookbook-examples. (although I think there is a typo in the book for this URL on the copy I have! ^_^) The sample code are complete, clean and easy to follow for each recipe example. The source code is in Maven based project, so you will get all the dependencies needed by just running the "install" phase. Open by any major IDE and you will start reading and compiling immediately. Because it's using Maven, you can also download the Camel dependencies with Source, and you can jump right into the framework code itself to analyze what's behind this cool project.

Because it's a cookbook, it does not go into too deep about Camel internal. But through the examples, many of the core concepts of Camel has been touched; and it serves as a great example and can be used as handy reference book. Because it covers the Camel concept briefly, it expected you to know little bit of the integration knowledge and background though. Things like Enterprise Integration Patterns and transport technologies used such as File, FTP, SEDA, JMS etc. The book also comes with many Spring based XML configuration examples, and it expects you to know some basic knowledge of bean configuration. But the xml configuration of Camel routes itself are very self explanatory, so readers should able to follow along easily.

If you work with Camel project, or have to start an integration project, I would recommend you to check out this book.

Friday, September 5, 2014

Django with Python 3 and MySQL database


I read many folks are having problems using MySQL db driver with Python 3, especially when setting up a Django app. The default Django 1.6.5 is only supporting the MySQLdb driver and that only works with Python 2.

I have been using mysql-connector-python with Python 3 and it has built-in django support as well. I had ran into trouble like this http://bugs.mysql.com/bug.php?id=73232, but it is fixed now with the latest mysql-connector-python 1.2.3 release. The mysql-connector-python also works with Python 2.7 as well, and it's a pure python library without native code, which makes the install much easier.

When installing mysql-connector-python, ensure you allow external hosted files like this

pip install --allow-all-external mysql-connector-python

If you are behind a firewall, use the proxy option

pip install --proxy my_proxy_server --allow-all-external mysql-connector-python

With these, now you can set your Django settings.py file with MySQL engine

DATABASES = {
    'default': {
        'ENGINE': 'mysql.connector.django',
        'NAME': 'mydb',
        'USER': 'myuser',
        'PASSWORD': 'mypassword',
    }
}


PS: My initial testing with Django 1.7 also works pretty well with mysql-connector-python. How sweet!

Thursday, August 21, 2014

Deploying applications or libraries to WebLogic Server using command line

Here is how you can automate deployment for WebLogic server using command line.

First source the env settings from the server:
$ source $ML_HOME/server/bin/setWLSEnv.sh

Deploy Library:
$ java weblogic.Deployer -nostage -deploy -library \
-adminurl localhost:7001 \
-username weblogic -password my_secret \
-targets myserver \
my_shared_lib.war


Deploy Application:
$ java weblogic.Deployer -nostage -deploy \
-adminurl localhost:7001 \
-username weblogic -password my_secret \
-targets myserver \
-name myapp.war myapp.war


For development, you likely want to use the "-nostage" meaning to deploy the app or library directly from the file system. This means any changes to that file location and a reload from WLS will take effect immediately.

For undeploy the command line options are same for library or app but with matching name.
$ java weblogic.Deployer -undeploy \
-adminurl localhost:7001 \
-username weblogic -password my_secret \
-targets myserver \
-name myapp_or_lib.war

Wednesday, August 20, 2014

WebLogic shared library deployment

When deploying a large WAR file application, it would be more easier to manage if we can separate the dependency jars away from the rest of the Web content; or at least those third party jars that do not update often. In this case, we usually call the jars content a "Shared Library" and the Web content the "Skinny WAR".

With WebLogic Server, you can easily deploy such two artifacts. Just seperate and package your WAR application into two. The share library would be simply another WAR with only the WEB-INF/lib content in it, while the Skinny war will be the rest of your application without the jar depependencies. On the shared lib WAR file, ensure you have an META-INF/MANIFEST.MF that specify the name and version like the following:

Implementation-Title: my_shared_lib
Implementation-Version: 1.0

Specification-Title: my_shared_lib
Specification-Version: 1.0

Extension-Name: my_shared_lib-1.0

Now your Skinny WAR would need to add an WEB-INF/weblogic.xml extension file to reference the library like this:

<weblogic-web-app>
    <library-ref>
        <library-name>my_shared_lib</library-name>
        <specification-version>1.0</specification-version>
        <implementation-version>1.0</implementation-version>
        <exact-match>true</exact-match>
    </library-ref>
</weblogic-web-app>



With these two packaged, now turn to your WLS admin console, you will find "Deployments" menu link on left, and on right, you click "Install" button. The next screen will prompt you to choose which type of deployment to install: "Library" (Shared Lib War) or "Application" (Skinny War). Re-run this twice, each with your two seperated WAR files you just built.



The WLS will combine the two when running your WAR application. This comes handy if you are to deploy multiple instances of your Skinny war application, but now you only need one shared lib.

NOTE: Ensure you select at least one, and the same Target servers where you deploy the Library and Application. Else your application will not be deployed and run.