Thursday, May 31, 2012

java.lang.NoClassDefFoundError: Could not initialize class javax.crypto.SunJCE_b in SSL HTTPS Solved


log4j:WARN No appenders could be found for logger (org.springframework.web.client.RestTemplate).
log4j:WARN Please initialize the log4j system properly.
Exception in thread "main" java.lang.NoClassDefFoundError: Could not initialize class javax.crypto.SunJCE_b
at javax.crypto.KeyGenerator.a(DashoA13*..)
at javax.crypto.KeyGenerator.(DashoA13*..)
at javax.crypto.KeyGenerator.getInstance(DashoA13*..)
at com.sun.net.ssl.internal.ssl.JsseJce.getKeyGenerator(JsseJce.java:223)
at com.sun.net.ssl.internal.ssl.RSAClientKeyExchange.(RSAClientKeyExchange.java:89)
at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverHelloDone(ClientHandshaker.java:744)
at com.sun.net.ssl.internal.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:238)
at com.sun.net.ssl.internal.ssl.Handshaker.processLoop(Handshaker.java:593)
at com.sun.net.ssl.internal.ssl.Handshaker.process_record(Handshaker.java:529)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:925)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1170)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1197)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1181)
at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:434)
at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:166)
at sun.net.www.protocol.https.HttpsURLConnectionImpl.connect(HttpsURLConnectionImpl.java:133)
at org.springframework.http.client.SimpleClientHttpRequest.executeInternal(SimpleClientHttpRequest.java:69)
at org.springframework.http.client.AbstractClientHttpRequest.execute(AbstractClientHttpRequest.java:52)
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:438)
at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:401)
at org.springframework.web.client.RestTemplate.exchange(RestTemplate.java:377)
at com.test.TestSecureHTTP.main(TestSecureHTTP.java:42)




I received the above error when i was trying to call a RESTFUL Webservice using restTemplate.exchange. 


REASON FOR THIS : Sun has changed the location of SUNJCE_b in Java 6 and above so it is no more able to find this class in the path specified as HTTPClient which underlies resttemplate is searching for this class in wrong package. 


SOLUTION:
I tried fixing this by adding old jce.jar which contains the class above JDK in Eclipse configure build path setting but it dis not work . 


Finally i got the code working by adding the following lines of code in my program

             try {
Class.forName("javax.crypto.SunJCE_b");
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

Complete program below



package com.test;


import java.util.Properties;


import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestTemplate;


import com.cisco.swtg.bss.util.Base64Coder;


public class TestSecureHTTP {

public static void main(String[] args) {

Properties props= new Properties();
props.put("javax.net.ssl.trustStoreType","jks");
   props.put("javax.net.ssl.trustStore","C:\\trust.jks");

   props.put("java.home", "C:\\Program Files\\Java\\jdk1.7.0_04");
   try {
Class.forName("javax.crypto.SunJCE_b");
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
   System.setProperty("java.protocol.handler.pkgs","com.sun.net.ssl.internal.www.protocol");
   props.put("javax.net.ssl.trustStorePassword","changeit");
   System.setProperties(props);
   HttpHeaders entityHeaders = new HttpHeaders();


entityHeaders.set("content-type", "application/json");

HttpEntity requestEntity = new HttpEntity(entityHeaders);
RestTemplate restTemplate = new RestTemplate();
ResponseEntity result= restTemplate.exchange("THE URL", HttpMethod.GET, requestEntity, String.class);
System.out.println(result.getBody());

   
}


}


Saturday, May 12, 2012

Concurrent file downloads using POST iframe and form

Recently i was faced with a scenario where user would select a few files from a list and click download. All the downloads should start in parallel . The file was supposed to be downloaded from a POST url so we could not use the regular hidden iframe since we could not send POST parameters to an iframe. Following is the solution i came up with after searching the internet. All credits go to the original authors. PLease refer links below

Related StackOverflow Question
Detecting the File Download Dialog In the Browser
Best Link on this subject

My Sample code :



Friday, May 4, 2012

Apple Push Notification in Java

Google project http://code.google.com/p/javapns/ for send ing push notifications.

JavaPNS 2.2

JavaPNS is a Java library to send notifications through the Apple Push Notification Service

Welcome to the JavaPNS project, home of the most user-friendly, powerful and fine-tuned Java library for APNS! This fully-featured Java library allows developers to push notifications to iOS devices (iPhone, iPod, iPad, etc.) through the Apple Push Notification Service using a simple yet powerful set of tools. First-time users will find the library to be extremely easy to use (start with a single line of code!), while advanced users will benefit from the library's flexible design and scalability features.

Capabilities

  • Start sending notifications using a single line of code
  • Get started quickly with smart default settings
  • Easily switch between Apple's sandbox or production services
  • Use predefined simple notifications, or create custom and/or complex payloads
  • Benefit from the enhanced notification format
  • Send thousands of notifications using the built-in multithreaded transmission engine
  • Examine push notification results immediately and accurately
  • Query the Feedback Service with a single line of code to find inactive devices
  • Auto-resend notifications ignored by Apple servers after an error
  • Push notifications to Apple's Newsstand application with one line of code
  • Setup connection pools (queues) in no time
  • Use bundled command-line tools to test push notification and feedback
  • Rely on the library's strong error and exception management
  • Get started quickly thanks to the built-in safeguards against common mistakes
  • Build upon JavaPNS's developer-friendly API to extend its functionalities
  • Learn everything about the library through its complete and up-to-date javadoc
  • and much more!

Wednesday, May 2, 2012

sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

10754 [main] ERROR FileBrokerServiceHdlr  - sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
    at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java:174)
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1649)
    at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Handshaker.java:241)
    at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Handshaker.java:235)
    at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1206)
    at com.sun.net.ssl.internal.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:136)
    at com.sun.net.ssl.internal.ssl.Handshaker.processLoop(Handshaker.java:593)
    at com.sun.net.ssl.internal.ssl.Handshaker.process_record(Handshaker.java:529)
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:893)
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1138)
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.writeRecord(SSLSocketImpl.java:632)
    at com.sun.net.ssl.internal.ssl.AppOutputStream.write(AppOutputStream.java:59)
    at java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.java:65)
    at java.io.BufferedOutputStream.flush(BufferedOutputStream.java:123)
    at org.apache.commons.httpclient.HttpConnection.flushRequestOutputStream(HttpConnection.java:828)
    at org.apache.commons.httpclient.HttpMethodBase.writeRequest(HttpMethodBase.java:2116)
    at org.apache.commons.httpclient.HttpMethodBase.execute(HttpMethodBase.java:1096)
    at org.apache.commons.httpclient.HttpMethodDirector.executeWithRetry(HttpMethodDirector.java:398)
    at org.apache.commons.httpclient.HttpMethodDirector.executeMethod(HttpMethodDirector.java:171)
    at org.apache.commons.httpclient.HttpClient.executeMethod(HttpClient.java:397)
    at org.apache.commons.httpclient.HttpClient.executeMethod(HttpClient.java:323)
    at com.cisco.csc.broker.FileBrokerServiceHdlr.doGet(FileBrokerServiceHdlr.java:268)
    at com.cisco.csc.CSCDownloadHandler.doGet(CSCDownloadHandler.java:78)
    at com.cisco.swtg.sasi.web.controller.fileservice.FileDownloadController.processDownload(FileDownloadController.java:130)
    at com.cisco.swtg.sasi.web.controller.fileservice.FileDownloadController.main(FileDownloadController.java:194)
Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
    at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:323)
    at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:217)
    at sun.security.validator.Validator.validate(Validator.java:218)
    at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:126)
    at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:209)
    at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:249)
    at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1185)
    ... 20 more
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
    at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:174)
    at java.security.cert.CertPathBuilder.build(CertPathBuilder.java:238)
    at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:318)
    ... 26 more




If you get the above exception in your Eclipse . PLease follow the steps below to remove this. BTW this happens because the HTTPClient does not have the certificate sent by the server in its trusted certificate list.

1) Download Portecle (google it). It is a java tool for importing certificates.




2) Go to the URL the HTTPClient is pointing to eg: https://wsgx-dev.xyz.com in forefox. It will give some validation error on the page . That is fine . Just click on the left to the URL in the browser URL and you will see the certificate dialog. The process is shown above. Finally click on export and save it on your file system.

3) Now go to C:\Program File \java \ jdk1.xx\ jre \lib\security [Path for jdk i am using for my eclipse] and open the file cacerts. This is the file which contains the certificates for jdk on my machine.

Open cacerts with portecle . It will ask for password which is : changeit . Now import the trusted ceritficate from the file system where you saved your cetificate earlier. Save the keystore.

Now you should be able to run your program and it will not give the erro.