Thursday, December 1, 2011

IE7 Preserve Whitespace Problem and Solution

Overview
Internet Explorer 7 has a well documented problem when it comes to using innerHTML and dynamically generating content which needs to preserve whitespace.  There is a lot information on the Internet about using the CSS properties white-space, word-wrap, and a multitude of other properties, hacks, and tricks to solve this problem.  However I found none of them worked.  After a few days of research I have a simple solution which I will explain here.

The Problem
Here is the problem.  You are building a dynamic website and in your database you have data which is formatted using newlines and spaces and looks like this:

Hello        Doctor             Name
    Continue
Yest..
 ..erday

Tomorrow


Your website is to pull this data from the database and display it on the page.  The implementation to do this will vary greatly, but essentially you will have an empty <div> to hold the data and you'll use jQuery to look up the <div> by ID then you will set the <div>'s HTML content.  Here is a very basic version of this:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
    <head>               
    </head>
    <body>       
        <div id="theData"></div>       
        <script src="jquery-1.6.2.min.js"></script>
        <script>
            var theData = "Hello        Doctor             Name\n    Continue\nYest..\n ..erday\n\nTomorrow";
            $(document).ready(
                function() {
                    $("#theData").html(theData);
                }
            );
        </script>
    </body>
</html>


Of course when you run this in any browser, the white space and newlines in the text will be removed and you will see this on the screen:
Hello Doctor Name Continue Yest.. ..erday Tomorrow

So CSS to the rescue!  Use the font-family and white-space attributes to tell the browser how to format the text in the <div>.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
    <head>
        <style>
            #theData {
                font-family:monospace;
                white-space:pre-wrap;               
            }
        </style>

    </head>
    <body>       
        <div id="theData"></div>

        <script src="jquery-1.6.2.min.js"></script>
        <script>
            var theData = "Hello        Doctor             Name\n    Continue\nYest..\n ..erday\n\nTomorrow";
            $(document).ready(
                function() {
                    $("#theData").html(theData);
                }
            );
        </script>
    </body>
</html>


Of course you quickly realize this works in Firefox and Chrome but not IE (which is why you are reading this).  This resource http://web.student.tuwien.ac.at/~e0226430/innerHtmlQuirk.html gives a good explanation about what is happening in IE.  Although researching this problem will give you a headache, I found a solution which seems to work with all browsers and is quite easy.

The easiest thing to do is to wrap the data with <pre> tags before setting the inner HTML of the <div>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
    <head>
        <style>
            #theData {
                font-family:monospace;
                white-space: pre-wrap;               
            }
        </style>
    </head>
    <body>       
        <div id="theData"></div> 

        <script src="jquery-1.6.2.min.js"></script>
        <script>
            var theData = "Hello        Doctor             Name\n    Continue\nYest..\n ..erday\n\nTomorrow";
            $(document).ready(
                function() {                   
                    $("#theData").html( 

                       "<pre>" + theData + "</pre>" 
                     );
                }
            );
        </script>
    </body>
</html>


That's it!  Of course, remember your CSS has to change now since you need to format #theData pre{} now...

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
    <head>
        <style>
            #theData pre {
                margin:0;
                color:purple;               
            }
        </style>

    </head>
    <body>       
        <div id="theData"></div>       
        <script src="jquery-1.6.2.min.js"></script>
        <script>
            var theData = "Hello        Doctor             Name\n    Continue\nYest..\n ..erday\n\nTomorrow";
            $(document).ready(
                function() {

                    $("#theData").html( 
                       "<pre>" + theData + "</pre>" 
                     );
                }
            );
        </script>
    </body>
</html>

Enjoy!


Wednesday, June 8, 2011

Secure SSL EJB Communication with GlassFish

Introduction

The purpose of this article is to document how to establish secure SSL communication between a GlassFish EJB server and a GlassFish WEB server using keystore certificates with GlassFish 3.0.1.

Starting with Java Enterprise Edition 5, EJB technology changed dramatically.  Building on ideas introduced by Spring and other frameworks, the new EJB specifications created a new easy to use standard.  Applications can take advantage of the technology of the Enterprise Server instead of relying on 3rd party technologies.  The EJB container allows easy access to both local and remote Enterprise Java Beans (EJB). Clients such as a Servlets, can use dependency injection to get instances of these EJBs with no code differences using local vs. remote beans.

However, using remote Enterprise Java Beans results in network traffic between the Enterprise server hosting the EJBs and the client application using the EJBs.  With network traffic comes the possibility for security problems so the goal is to have the EJB communication secured with SSL.

This article will be a cheat sheet on the configuration.  The cheat sheet will provide the relevant information but it will be up to you to integrate it into your projects.  Subsequent parts will step through creating and configuring a real working example.

Cheat Sheet

EJB


Create a @Remote interface for your EJB
A @Remote interface for you EJB defines the methods which are available to remote clients accessing the remote EJB

@Remote
public interface AccountService {    
  public Account findAccount(int id);
}

Create a @Stateless implementation of the @Remote interface for your EJB
An implementation may be @Stateful or @Stateless but in this example create a @Stateless implementation of the remote interface. 
@Stateless
public class AccountServiceBean implements AccountService
{
    @Override
    @PermitAll
    public Account findAccount(int id)
   {
        System.out.println(
          String.format("ENTER findAccount(%d)",id)
        );
        Account account = new Account();
        account.setAccountId(id);
        return account;
    }
}

Create a sun-ejb-jar.xml file which configures the use of SSL for your EJB
The sun-ejb-jar.xml file is a GlassFish specific configuration file responsible for configuring EJBs.  Typically the EJBs are compiled into a JAR and then the JAR put into an EAR.  The sun-ejb-jar.xml file is saved in the META-INF directory of the JAR.
The sun-ejb-jar.xml file should contain an <ejb> configuration for each EJB which needs secure SSL communication access.
Except for the <ejb-name> value, all the rest of the values should remain the same. These were the combination of values I found to work properly. 
<!DOCTYPE sun-ejb-jar PUBLIC "-//Sun Microsystems, Inc.//
DTD GlassFish Application Server 3.0 EJB 3.1//EN"
"http://www.sun.com/software/appserver/dtds/sun-ejb-jar_3_1-0.dtd">
<sun-ejb-jar>
  <enterprise-beans>
    <ejb>
      <ejb-name>
        AccountServiceBean
      </ejb-name>
      <ior-security-config>
        <transport-config>
          <integrity>
            required
          </integrity>
          <confidentiality>
            required
          </confidentiality>
          <establish-trust-in-target>
            SUPPORTED
          </establish-trust-in-target>
          <establish-trust-in-client>
            REQUIRED
          </establish-trust-in-client>
        </transport-config>
        <sas-context>
          <caller-propagation>
            supported
          </caller-propagation>
        </sas-context>
      </ior-security-config>
    </ejb>
  </enterprise-beans>
</sun-ejb-jar>
 

Create a JAR file for your EJB
When you create the JAR file for your EJB, the directory structure must be:
MyBeans.jar
  /META-INF
    sun-ejb-jar.xml
  /com
    /mycompany
      *.class

WAR


Create a Servlet for your WAR
Create a Servlet which uses dependency injection to get an instance of the EJB.  Remember, from the Servlet's point of view it will only be dealing with a local JNDI lookup name and the @Remote interface for the EJB. Beyond this, the Servlet knows no other details. 
The @EJB lookup is a local JNDI lookup name.  This name only exists within the namespace of this WAR.  The web.xml and sun-web.xml files configure how this local JNDI lookup maps to a real EJB instance.  I like to use local lookup names because when the WAR is configured properly and the lookup succeeds I am confident the code looked up the correct thing.  The alternative is auto-lookup magic and not knowing how the resource is found and injected is not a good thing.
@WebServlet(
    name="AccountServlet"
  , urlPatterns= {"/account"}
)
public class AccountServlet extends HttpServlet
{
    // Remember, this is a
    //
    //  !! LOCAL JNDI LOOKUP NAME !!
    //
    // and this lookup name is only
    // used by this WAR.  How this
    // local lookup name maps to a
    // real EJB instance is configured
    // in web.xml and sun-web.xml
    @EJB(lookup="java:comp/env/ejb/Sam")
    AccountService accountService;
}
 


Create a web.xml for your WAR
The web.xml file must contain an <ejb-ref> element.  This element sets 2 values.
  1. The local JNDI lookup name your WAR file uses when trying to find the EJB
  2. The fully-qualified name of the @Remote EJB interface.
You will need an <ejb-ref> element for every local JNDI lookup you WAR performs. 
<?xml version="1.0" encoding="UTF-8"?>
<web-app 
  xmlns:xsi=
    "
http://www.w3.org/2001/XMLSchema-instance
  xmlns=
    "
http://java.sun.com/xml/ns/javaee
  xmlns:web=
    "
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd
  xsi:schemaLocation=
    "
http://java.sun.com/xml/ns/javaee
    
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd
  id="WebApp_ID" 
  version="2.5"

  <ejb-ref>
    <ejb-ref-name>
      ejb/Sam
    </ejb-ref-name>   
    <remote>
      org.ferris.ejb.account.AccountService
    </remote>
  </ejb-ref>
</web-app>

 
Create a sun-web.xml for your WAR
The sun-web.xml file is a GlassFish specific configuration file for your WAR.  Use the sun-web.xml file to map the local JNDI lookup the WAR with the real location of the EJB.  Having the WAR code only know about a local JNDI lookup makes this mapping easy and also allows for easy change of configuration between different environments (if needed).  
Some notes about the the value for <jndi-name>  below:
  1. It is displayed on multiple lines but in reality it should all be on 1 line! 
  2. Don't miss any of the ":", "/", or "!" characters
  3. [SERVER_NAME] - This is the name of the GlassFish server where the @Remote EJBs are deployed.
  4. [EAR_NAME] - This is the name of the EAR application, which is typically the name of the EAR file.  Suppose you deploy the "MyBeans.ear" file to GlassFish.  By default GlassFish will use "MyBeans" as the name of the EAR application.  This value can be overridden or changed, but typically it is the name of the EAR file.
  5. [JAR_NAME] - This is the name of the JAR file inside the EAR file which holds the beans.  Suppose you have an  "account.jar" file inside the "MyBeans.ear" file which holds the EJB classes for account information.  By default, GlassFish will use "account" as the module name.  This value can be overridden or changed, but typically it is the name of the JAR file.
  6. [BEAN_NAME] - This is of course the bean name.  It should match what is in the sun-ejb-jar.xml configuration file deployed with the beans.
  7. [FULLY_QUALIFIED_REMOTE_INTERFACE] - This value speaks for itself.  It is the fully qualified @Remote interface of the EJB.
<!DOCTYPE
  sun-web-app PUBLIC "-//Sun Microsystems, Inc.//DTD
  GlassFish Application Server 3.0 Servlet 3.0//EN"
  "
http://www.sun.com/software/appserver/dtds/sun-web-app_3_0-0.dtd"
>
<sun-web-app>
  <ejb-ref>
 
    <!--
     | local JNDI lookup name your code uses
     -->
    <ejb-ref-name>ejb/Sam</ejb-ref-name>
 
    <!--
     | The jndi-name value is the same
     | for both secure and non-secure
     | configuration.  The sun-ejb-jar.xml
     | file on the EJB server determines
     | if the two GlassFish instances should
     | establish a secure communications
    -->
    <jndi-name>
      corbaname
      :     
      iiop
      :
      [SERVER_NAME]
      :
      3700#java
      :
      global
      /
      [EAR_NAME]
      /
      [JAR_NAME]
      /
      [BEAN_NAME]
      !
      [FULLY_QUALIFIED_REMOTE_INTERFACE]
    </jndi-name>
  </ejb-ref>
</sun-web-app>


GlassFish Keystore Key Exchange

Secure EJB communication between two GlassFish servers is easiest when the servers can exchange certificates and automatically trust each other.  To do this, the certificates in the Keystore (keystore.jks) of each GlassFish server must be exported and then imported into the Truststore (cacerts.jks) of the other GlassFish server.

Export Cert From keystore.jks


Command for GlassFish EJB Server 
Execute the following command on the GlassFish EJB Server to export the GlassFish EJB Server certificate. 
C:>cd C:\glassfish\3.1\glassfish\domains\domain1\config
C:>keytool.exe -export -rfc -alias s1as -keystore keystore.jks -file GlassFishEJBServer.cer
The default password for keystore.jks is "changeit" 
 Command for GlassFish WEB Server 
Execute the following command on the GlassFish WEB Server to export the GlassFish WEB Server certificate.  
C:>cd C:\glassfish\3.1\glassfish\domains\domain1\config
C:>keytool.exe -export -rfc -alias s1as -keystore keystore.jks -file GlassFishWEBServer.cer
The default password for keystore.jks is "changeit"  



Exchange Cert Files
Assume you have exported both certificates and the names of the files are GlassFishEJBServer.cer and GlassFishWEBServer.cer.  Copy, sftp, or use whatever file transfer protocol you need to exchange the files between the servers.

Import Cert Into cacerts.jks


Command for GlassFish EJB Server
Execute the following command on the GlassFish EJB Server to import the GlassFish WEB Server certificate.
C:>cd C:\glassfish\3.1\glassfish\domains\domain1\config
C:>keytool.exe -import -noprompt -trustcacerts -alias glassfishwebserver -file GlassFishWEBServer.cer -keystore cacerts.jks
The default password for cacerts.jks is "changeit" 
Command for GlassFish WEB Server
Execute the following command on the GlassFish WEB Server to import the GlassFish EJB Server certificate.
C:>cd C:\glassfish\3.1\glassfish\domains\domain1\config
C:>keytool.exe -import -noprompt -trustcacerts -alias glassfishejbserver -file GlassFishEJBServer.cer -keystore cacerts.jks
The default password for cacerts.jks is "changeit" 



Conclusion 

The purpose of this article is to document how to establish secure SSL communication between an GlassFish EJB server and a GlassFish WEB server using keystore certificates with GlassFish 3.0.1.  This purpose was accomplished by first documenting the configuration of the EJB module, then documenting the configuration of the WEB module, then finally documenting how to exchange certificates between the two servers.  Although this article leaves out details on how to actually implement these steps, they should given enough information to integrate into your code/application/server specific setup.  Of course make comments or contact me with any questions.

Friday, April 29, 2011

Secure JDBC connection to MySQL from GlassFish

Introduction

Following up my article on Secure JDBC connection to MySQL from Java, It is often the case you Java code will not be connecting to the database directly but instead will lookup a connection from a container managed connection pool.  This article describes how to configure a GlassFish connection pool to connect to MySQL securely using keystore/truststore SSL keys.  Thanks much to Thomas Schaefer for this information.

GlassFish Connection Pool

Using the GlassFish administrator, creating a Connection Pool of MySQL database connections is easy.  To secure the communication, go to the "Additional Properties" tab and add these additional properties, of course replace the values between the [] with your own.


Name                               Value
requireSSL                         true
useSSL                             true
trustCertificateKeyStorePassword   [password_to_truststore]
clientCertificateKeyStoreUrl       file:/c:/temp/keystore.jks
clientCertificateKeyStoreType      JKS
clientCertificateKeyStorePassword  [password_to_keystore]
trustCertificateKeyStoreType       JKS
password                           [database_user_password]
trustCertificateKeyStoreUrl        file:/c:/temp/cacerts.jks  
user                               [databse_user_name]
url                                jdbc:mysql://[server_name]

The keystore.jks and cacerts.jks files are the tricky part of this configuration.  How you use them will depend on your situation but in general, cacerts.jks will have your certificate authority added to it and keystore.jks will have a certificate added to it signed by your certificate authority.  When the JDBC driver attempts to connect to the database, the certificate from keystore.jks is presented to the database server and the database server accepts it since the certificate was signed by your certificate authority.  In the same way, the database server will present a certificate to the GlassFish server and GlassFish will accept it because your certificate authority is in cacerts.jks.

Tuesday, April 26, 2011

Secure JDBC connection to MySQL from Java

Introduction

Connecting to a database with JDBC is easy but gets a little more complicated if a secure connection is needed.  This is how a secure connection to MySQL is established using keystore/truststore SSL keys.  Overall, nothing too spectacular here but a useful reference.

Java

The Java code to get a secure JDBC connection to MySQL is easy.  It is a matter of adding properties to the URL connection string which inform the MySQL JDBC driver to use a secure connection.

  String username = "[USERNAME]";
  String password = "[PASSWORD]";

        
  StringBuilder url = new StringBuilder();
  url.append("jdbc:mysql://[SERVER]/[SCHEMA]?")
     .append("useSSL=true&")
     .append("requireSSL=true&")
  ;

   

  Connection conn = DriverManager.getConnection(url.toString(), username, password);

System Properties

The properties on the URL connection string tell the MySQL JDBC driver to use a secure connection but you still need to tell your application where the keystore/truststore SSL keys are located.  Do this using the following system properties when you start the JVM.

  -Djavax.net.ssl.trustStore=C:\temp\cacerts.jks 
  -Djavax.net.ssl.trustStorePassword=[PASSWORD]
  -Djavax.net.ssl.keyStore=C:\temp\keystore.jks 
  -Djavax.net.ssl.keyStorePassword=[PASSWORD]

These files will of course need the the keys off your MySQL server.