Friday, June 28, 2013

How to find unused jars in Java EE web application?

      I was exploring options on how to identify unused jar files in a web application packaged in war/ear file. One could argue that they are unused and why should I bother it as they don't get loaded by the classloader. In fact, it gives couple of advantages. By doing this, the war file size will be smaller that makes it faster to deploy. During deploy, the application server scans all the jar files for tag library definitions(tlds) and possibly other things. By removing unused ones, the startup time will get reduced (eventhough it is not noticeable) There are multiple ways to do it depending upon the frameworks/libraries that you use in your application.

Maven's dependency plugin
     Maven has a plugin to analyze the dependencies of your web application. It uses the project's pom.xml to identify the dependent jars (including transitive dependencies).
mvn dependency:analyze - go to your web project folder and run this command; This will list used and unused jars. One caveat is that this works only if your application does not rely on frameworks such as spring, guice. Otherwise the jars that maven classifies as unused might be used while the application is running.

Use java's -verbose:class option
This would be the best solution if your web application uses dynamic class loading and maven's dependency plugin does not help. The solution would be a multistep approach as described below:-
  1.  Add a new JVM parameter -verbose:class to your server. This would log the jar files from which each class is loaded.
  2. Deploy your web application and do a functional test (to capture the classes that are dynamically loaded).
  3. Grep the logs for individual jar files.
  4. If you are using maven, identify the group id and artifact id from the jar file name.
  5. Remove the jar files that are not listed in step 3.



Monday, June 24, 2013

java.lang.OutOfMemoryError: requested bytes for GrET in growableArray.cpp. Out of swap space?

Did you get an OutOfMemoryError while running jhat?

This is a bug. Check your jdk version and upgrade to anything more than jdk1.6v22.


Details:-
If you have encountered an OutOfMemoryError while running jhat and you are sure that the system has enough memory, it could be due to a bug in java. I encountered the following error while trying to get details of the heap dump (heap.bin).
C:\> jhat -J-mx1024m heap.bin

# A fatal error has been detected by the Java Runtime Environment:
#
# java.lang.OutOfMemoryError: requested 83886080 bytes for GrET in C:\BUILD_AREA
\jdk6_16\hotspot\src\share\vm\utilities\growableArray.cpp. Out of swap space?
#
#  Internal Error (allocation.inline.hpp:39), pid=10168, tid=10848
#  Error: GrET in C:\BUILD_AREA\jdk6_16\hotspot\src\share\vm\utilities\growableArray.cpp
#
# JRE version: 6.0_16-b01
# Java VM: Java HotSpot(TM) Client VM (14.2-b01 mixed mode windows-x86 )
# An error report file with more information is saved as:
# C:\hs_err_pid10168.log
#
# If you would like to submit a bug report, please visit:
#   http://java.sun.com/webapps/bugreport/crash.jsp



Thursday, June 13, 2013

com.sun.xml.wss.impl.WssSoapFaultException: Certificate validation failed

Lets talk about how to resolve certificate validation failed error while receiving SOAP based web service requests from clients. If you receive an error on the server side as given below, you are not alone. Lets see below how to resolve the error.

Exception stack trace:-

SEVERE: WSS1353: Error occurred while resolving key information
com.sun.xml.wss.impl.WssSoapFaultException: Certificate validation failed
at com.sun.xml.wss.impl.SecurableSoapMessage.newSOAPFaultException(SecurableSoapMessage.java:322)
at com.sun.xml.wss.impl.dsig.KeySelectorImpl.resolveToken(KeySelectorImpl.java:1317)
at com.sun.xml.wss.impl.dsig.KeySelectorImpl.resolve(KeySelectorImpl.java:625)
at com.sun.xml.wss.impl.dsig.KeySelectorImpl.select(KeySelectorImpl.java:232)
at org.jcp.xml.dsig.internal.dom.DOMXMLSignature$DOMSignatureValue.validate(DOMXMLSignature.java:500)
at org.jcp.xml.dsig.internal.dom.DOMXMLSignature.validate(DOMXMLSignature.java:232)
at com.sun.xml.wss.impl.dsig.SignatureProcessor.verify(SignatureProcessor.java:772)
at com.sun.xml.wss.impl.filter.SignatureFilter.process(SignatureFilter.java:514)
at com.sun.xml.wss.impl.HarnessUtil.processWSSPolicy(HarnessUtil.java:79)
at com.sun.xml.wss.impl.HarnessUtil.processDeep(HarnessUtil.java:252)
at com.sun.xml.wss.impl.SecurityRecipient.processMessagePolicy(SecurityRecipient.java:849)
at com.sun.xml.wss.impl.SecurityRecipient.processMessagePolicy(SecurityRecipient.java:801)
at com.sun.xml.wss.impl.SecurityRecipient.validateMessage(SecurityRecipient.java:242)
at com.sun.xml.wss.impl.misc.XWSSProcessor2_0Impl.verifyInboundMessage(XWSSProcessor2_0Impl.java:134)
at org.springframework.ws.soap.security.xwss.XwsSecurityInterceptor.validateMessage(XwsSecurityInterceptor.java:162)
...

Solution:-
If you are exposing a secured web service using Spring WS and encountered the following error while handling client request, it means that your truststore does not have the certificate sent by the client. If you think the client is valid, add the certificate to your truststore.

How to import certificate into truststore?

keytool -import -trustcacerts -alias client1 -file clientcertificate.cer -keystore mytruststore.jks -storepass mypassword





Wednesday, June 12, 2013

Java security interview questions for senior developer

Lets talk about some interview questions that could be asked during senior Java EE developer who claims to have invoked REST or SOAP secured web services.

Q: Is the security configuration different for Apache HttpClient from java.net.HttpsURLConnection?
      Yes; it does. For both types, an instance of SSLContext needs to be initialized with respective     keystore/truststore. HttpsURLConnection could be configured by invoking setSSLSocketFactory(); apache http client by registering https schema with a corresponding implementation of org.apache.http.conn.ssl.SSLSocketFactory.


Q: Does SSLContext.getInstance() return new instance every time the method is invoked?
     Yes; SSLContext.getInstance() returns new instance each time the method is invoked. It will not have a keystore and truststore hooked to it. init() would need to be called to initialize it. null passed in for the keystore/truststore will use the default implementation for the respective store.


Q: What security configuration does HttpsURLConnection use if a security configuration is not specified?
     HttpsURLConnection uses SSLSocketFactory default implementation retrieved by SSLContext.getDefault().


Q: Why do we create protocols like myhttps, abchttps etc.?
The standard approach while using apache http client 3.1 is to define a SSLContext with keystore/truststore and register a new protocol such as abchttps with the newly defined SSLContext. Then your web service URL will be prefixed with abchttps instead of https.


Q: This seems to be clumsy; is there a better alternative?
A better approach would be to upgrade to apache httpcomponents 4.x which is a successor to apache httpclient 3.x (reached EOL). In 4.x, you could define a SSLContext and register https protocol with SSLContext. The https protocol (aka scheme) will be registered to your httpclient's connection manager. The key point to note here is that you could define multiple https protocol and register it in different connection managers to have different keystore/truststore for different web service calls.

Monday, June 10, 2013

Core java security interview questions and answers for java developer


Here are some of the core java interview questions related to java security that you could expect in an interview for a Java developer.

Q What is the difference between a keystore and a truststore?
      The truststore contains the trusted entries and root certificates. The keystore contains the private keys. They both have the same file name extension (.jks).

What does JKS stand for?
     Java key store

What are the other standards for managing keystores that you know of?
     Java understands only JKS. Other systems include PKCS12 and others typically well known in non-java world.

Do I always need a keystore?
     No; you need it only if you intend to authenticate yourself against the server.

What are the contents of a jks file?
    A jks file typically contains private/public key pairs, public keys/certificates, root certificate authority entries.

Is there a default truststore?
    Each java installation will have a /lib/security/cacerts which contains certificates of all the popular root certificate authorities.

Is this same as the certificate repository used by browsers?
   No; each browser has their own certificate repository which contains the popular root certificate authorities whom the browser trust.

Can I use same jks file as both truststore and keystore?
Yes; you can. In this case, the jks file contains private keys and trusted certificates/ca entries.

How do you configure truststore in your web application?
   The default truststore/keystore could set by setting VM parameter (-D option) or invoke System.setProperty() for the following properties:-
Keystore: -Djavax.net.ssl.keyStore -Djavax.net.ssl.keystorePassword 
Truststore: -Djavax.net.ssl.truststore -Djavax.net.ssl.truststorePassword

What is 2 way SSL ?
    In one way SSL  (aka typical https connection), the server authenticates itself to the client using server certificate. In 2 way SSL , in addition to the above step, the client authenticates itself to the server.

How do you configure it?
   This involves additional configuration of setting the keystore in addition to setting the truststore.

What is a SSLContext?
    SSLContext is java class that acts as factory for secure socket factories. To configure a custom keystore/truststore, you get an instance of it and intialize it with keystore and truststore.

How do you configure a specific truststore for a https connection?
    If you need to configure a specific truststore for a particular https connection (be it a web service or https get/post url), you could define a SSLContext with a keystore and truststore. The new SSLContext object will be set in the https connection. 

What are the errors that you have encountered during your development?
    The common errors are
       1. certificate_unknown
       2. java.security.InvalidAlgorithmParameterException: the trustAnchors parameter must be non-empty
       3. unable to find valid certification path to requested target

When do you get a certificate unknown error?
    If the server side certificate is not present in your truststore, this error will occur. One of the most common reasons for this would be a custom truststore that does not contain the certificates or the server presents itself with self-signed certificate or a certificate signed by non-public certificate issuing authority. Most organizations will have their own root ca's to issue certificates for testing environments and internal use.

How do you solve the certificate unknown error?
    Get the certificate presented by the server; import it to your truststore. There are 2 ways to do this. The simplest approach is to give the URL in the browser, view the certificate, export it and import the same to your truststore. The second approach would be to write a sample piece of code that connects to https url and write the certificate contents into file; This could be imported to your truststore.

How do you debug a SSL handshake issue?
    To debug the issues during a ssl handshake, we need to set the VM parameter -Djavax.net.debug=all. This will spit out the debug information in your log file.


Wednesday, January 16, 2013

PropertiesConfiguration - update properties without deleting commented lines and preserving layout

The Properties class provided by java does not provide fancy methods to manage the existing layout and leaving the comments in the properties while when we read and update properties from java program. The comments will be deleted and the layout is not guaranteed.  Apache commons PropertiesConfiguration provides a facility that java.util.Properties does not provide; it helps to maintain the layout and preserve the comments in the properties file. Hence it is safe to update your properties file without corrupting the existing layout.

The following code will read properties file, remove few properties and save it. 
public void refineProperties(String propFilename) {
try {
PropertiesConfiguration props = new PropertiesConfiguration(propFilename);
Iterator it = props.getKeys();
while(it.hasNext()) {
String propName = it.next();
if("
jdbc.connection".equals(propName)) {
props.clearProperty(miss);
}
}
props.save();
} catch (ConfigurationException e) {
e.printStackTrace();
}
Input properties:-
#Properties for my envt
include = common.propertes
#Connection specific properties
jdbc.connection = NONE
jdbc.userid = tom
jdbc.password = tiger

After cleanup:-
The properties file still has the comments and the same layout as the input
#Properties for my envt
include = common.propertes
#Connection specific properties
jdbc.userid = tom
jdbc.password = tiger 



Wednesday, September 26, 2012

generate report from java


package com.test;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.HashMap;

import org.eclipse.birt.report.engine.api.EngineConfig;
import org.eclipse.birt.report.engine.api.EngineConstants;
import org.eclipse.birt.report.engine.api.HTMLRenderContext;
import org.eclipse.birt.report.engine.api.HTMLRenderOption;
import org.eclipse.birt.report.engine.api.IReportRunnable;
import org.eclipse.birt.report.engine.api.IRunAndRenderTask;
import org.eclipse.birt.report.engine.api.ReportEngine;

public class BirtTest {

     public static void main(String[] args) {
          //Variables used to control BIRT Engine instance
          EngineConfig conf = null;
          ReportEngine eng = null;
          IReportRunnable design = null;
          IRunAndRenderTask task = null;
          HTMLRenderContext renderContext = null;
          HashMap contextMap = null;
          HTMLRenderOption options = null;
          //Now, setup the BIRT engine configuration. The Engine Home is hardcoded
          //here, this is probably better set in an environment variable or in
          //a configuration file. No other options need to be set
          conf = new EngineConfig();
          conf.setEngineHome("C:/eclipse-birt/eclipse/birt-runtime-4_2_0/ReportEngine");
       
          //Create new Report engine based off of the configuration
          eng = new ReportEngine( conf );
       
          //With our new engine, lets try to open the report design
          try
          {
               design = eng.openReportDesign("C:/sanker/birt/birt-test/new_report.rptdesign");
          }
          catch (Exception e)
          {
               System.err.println("An error occured during the opening of the report file!");
               e.printStackTrace();
               System.exit(-1);
          }
       
          //With the file open, create the Run and Render task to run the report
          task = eng.createRunAndRenderTask(design);
       
          //Set Render context to handle url and image locataions, and apply to the
          //task
          renderContext = new HTMLRenderContext();
          renderContext.setImageDirectory("image");
          contextMap = new HashMap();
          contextMap.put( EngineConstants.APPCONTEXT_HTML_RENDER_CONTEXT, renderContext );
          task.setAppContext( contextMap );
          ResultSet rs = getResultSet(); // a function that executes the query and returns resultset
          task.setParameterValue("myResultSet", rs);
          //This will set the output file location, the format to rener to, and
          //apply to the task
          options = new HTMLRenderOption();
          options.setOutputFileName("C:/sanker/birt/output/output.html");
          options.setOutputFormat("html");
          task.setRenderOption(options);
       
          try
          {
               task.run();
          }
          catch (Exception e)
          {
               e.printStackTrace();
          }
       
          eng.destroy();
     }
   
     static ResultSet getResultSet() {
    ResultSet rs = null;
    try {
Connection con = getConnection();
Statement stmt = con.createStatement();
stmt.execute("select id, name from A");
rs = stmt.getResultSet();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
    return rs;
     }
   
     static Connection getConnection() {
    try {
Class.forName("oracle.jdbc.driver.OracleDriver");
return DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:xe","sanker","password");
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
    return null;
     }
}


/*******************************************************/
package com.test;

import java.sql.ResultSet;
import java.sql.SQLException;

import org.eclipse.birt.report.engine.api.script.IReportContext;
import org.eclipse.birt.report.engine.api.script.IUpdatableDataSetRow;
import org.eclipse.birt.report.engine.api.script.ScriptException;
import org.eclipse.birt.report.engine.api.script.eventadapter.ScriptedDataSetEventAdapter;
import org.eclipse.birt.report.engine.api.script.instance.IDataSetInstance;

public class MyScriptedSetAdapter extends ScriptedDataSetEventAdapter {

ResultSet resultSet;

@Override
public boolean fetch(IDataSetInstance dataSet, IUpdatableDataSetRow row)
throws ScriptException {
try {
if(resultSet.isAfterLast())
return false;// to indicate that there are no more rows left to process
row.setColumnValue("ID", resultSet.getInt(1));
row.setColumnValue("NAME", resultSet.getString(2));
resultSet.next();
return true; // to indicate that more rows to follow
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return false;
}
}

@Override
public void open(IDataSetInstance dataSet) throws ScriptException {
super.open(dataSet);
try {
if(resultSet != null)
resultSet.next();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

@Override
public void beforeOpen(IDataSetInstance dataSet, IReportContext reportContext) throws ScriptException {
super.beforeOpen(dataSet, reportContext);
//retrieve the parameter myResultSet set from the java class in Step 1
System.out.println("myResultSet="+reportContext.getParameterValue("myResultSet"));
resultSet = (ResultSet)reportContext.getParameterValue("myResultSet");
}
}