Event Callbacks in Java

Event callbacks in Java (including Android) are supported starting in v9.5.0.52. To receive event callbacks, first create a Java class derived from one of the Chilkat event callback classes. The event callback classes are: CkBaseProgress, CkHttpProgress, CkZipProgress, CkFtp2Progress, CkMailManProgress, CkTarProgress, and CkSFtpProgress.

All future Chilkat classes will only use CkBaseProgress. Theses event callback classes will be documented in the “Events” section of each class’s online reference documentation.

Here is an example of an HTTP download using event callbacks in Java. First we have the MyHttpProgress derived from CkHttpProgress. Following that, we have the simple Java program that installs the event handler and does the HTTP download. Event callbacks will also happen with the asynchronous version of the methods, but beware of the fact that when asynchronous, the task is running in a background thread and the callback occurs in the background thread.

import com.chilkatsoft.CkHttpProgress;
import com.chilkatsoft.CkTask;


public class MyHttpProgress extends CkHttpProgress 
{	
  public boolean AbortCheck()
  	{
      System.out.println("AbortCheck");
      // Return true to abort, false to allow the method to continue.
      return false;
  	}
  	
  // pctDone is a value from 0 to 100
  // (it is actually value from 0 to the PercentDoneScale property setting)
  public boolean PercentDone(int pctDone)
  {
    System.out.println(pctDone);
    // Return true to abort, false to allow the method to continue.
    // Note: A PercentDone event is the equivalent of an AbortCheck.  
    // When PercentDone events are frequently firing, AbortCheck events are suppressed.
    // AbortCheck events will fire when the time between PercentDone events is longer 
    // than the HeartbeatMs property setting.
    return false;
  }
  
  public void ProgressInfo(String name, String value)
  {
    System.out.println(name + ": " + value);
  }
  
  public void TaskCompleted(CkTask task)
  {
     System.out.println("task completed!");
  }
  
  }

The synchronous Java program w/ event callbacks… (the asynchronous version follows..)

import com.chilkatsoft.CkHttp;

public class HttpWithEvents {
	
  static {
    try {
    	
    	System.loadLibrary("chilkat");
    	
    } catch (UnsatisfiedLinkError e) {
      System.err.println("Native code library failed to load.\n" + e);
      System.exit(1);
    }
  }


	
  public static void main(String argv[])
  	{
    CkHttp http = new CkHttp();
    
    // Install an event callback handler to get progress events.
    MyHttpProgress myProgress = new MyHttpProgress();
    http.put_EventCallbackObject(myProgress);
    
    boolean success;

    //  Any string unlocks the component for the 1st 30-days.
    success = http.UnlockComponent("Anything for 30-day trial");
    if (success != true) {
        System.out.println(http.lastErrorText());
        return;
    }

    //  Download a file at a URL.
    success = http.Download("http://www.chilkatsoft.com/download/9.5.0.51/ChilkatDotNet45-9.5.0-x64.zip","ChilkatDotNet45-9.5.0-x64.zip");
    if (success != true) {
        System.out.println(http.lastErrorText());
        return;
    }
    
    System.out.println("OK");
  	}
  }

The asynchronous Java program w/ event callbacks…

import com.chilkatsoft.CkHttp;
import com.chilkatsoft.CkTask;

public class AsyncHttp {
	
  static {
    try {
    	
    	System.loadLibrary("chilkat");
    	
    } catch (UnsatisfiedLinkError e) {
      System.err.println("Native code library failed to load.\n" + e);
      System.exit(1);
    }
  }


	
  public static void main(String argv[])
  	{
    CkHttp http = new CkHttp();
    
    // Install an event callback handler to get progress events.
    MyHttpProgress myProgress = new MyHttpProgress();
    http.put_EventCallbackObject(myProgress);
    
    boolean success;

    //  Any string unlocks the component for the 1st 30-days.
    success = http.UnlockComponent("Anything for 30-day trial");
    if (success != true) {
        System.out.println(http.lastErrorText());
        return;
    }

    //  Download a file at a URL.
    CkTask task = http.DownloadAsync("http://www.chilkatsoft.com/download/9.5.0.51/ChilkatDotNet45-9.5.0-x64.zip","ChilkatDotNet45-9.5.0-x64.zip");
    if (success != true) {
        System.out.println(http.lastErrorText());
        return;
    }
    
    task.put_UserData("chilkatDotNet45");
    
    if (!task.Run()) {
        System.out.println(task.lastErrorText());
        return;
	}
  
    System.out.println("OK, task is running...");
    
    // Wait a max of 10 seconds for it to finish.
    success = task.Wait(10000);
    
    // What is the task status?
    System.out.println("task status = " + task.status());
  	}
  }

Java System.loadLibrary w/ GlassFish application server

** The following is a helpful note from a Chilkat customer using the Chilkat Java API in a GlassFish environment:

FYI I managed to solve the problem. The following is what I did (in case you may want to help others with a similar need in future) to enable the RSA component to run within a Java EE6 web application using GlassFish v3

1. Copy the Chilkat native library to a path listed in java.library.path. The default on a Mac (OS X 10.6) is \System\Library\Java\Extensions.

2. Create a singleton class object in Java and place the call System.loadLibrary(String) within a static block (i.e. static { try { System.loadLibrary(“chilkat”); } catch (UnsatisfiedLinkError e) {//say or do something clever}}). There is excellent guidance about creating singletons at http://www.javacoffeebreak.com/articles/designpatterns/index.html and https://www.securecoding.cert.org/confluence/display/java/MSC07-J.+Prevent+multiple+instantiations+of+singleton+objects. Also create all necessary component manipulation methods (e.g. encrypt/decrypt) within the singleton.

3. Compile the singleton class into a jar file and make it available to the web application as a library resource.

4. Call the singleton from a convenient web application bean.

Chilkat Java library now available for MAC OS X

The Chilkat Java library is now available for MAC OS X. For the download link and more information, see http://www.chilkatsoft.com/installJavaMacOSX.asp

Chilkat will soon release MAC OS X compatible builds for Perl, Python, and Ruby. Following that, builds for the IOS (IPhone) will be released, along with Objective-C/C++ native libraries for both MAC OS X and IPhone.

Using Chilkat for Java in Eclipse on Windows

Here are the steps I followed to use Chilkat’s Java library in an Eclipse project on Windows:

  1. Open Project->Properties, select “Java Build Path”, click on the “Add External JARs…” button and add the “chilkat.jar”
  2. (still within the Project Properties dialog) Click on the “Run/Debug Settings”, select your Java class, then click on the “Edit…” button.  Select the “Arguments” tab, then add  -Djava.library.path=”C:\chilkatJava;${env_var:PATH}” where “C:\chilkatJava” is the directory path containing the “chilkat.dll” file.
  3. The chilkat.dll is loaded at runtime using this code snippet:
	  static {
		    try {
		        System.loadLibrary("chilkat");
		    } catch (UnsatisfiedLinkError e) {
		      System.err.println("Native code library failed to load.\n" + e);
		      System.exit(1);
		    }
		  }

Java Create Signature / Chilkat Verify Interoperability

The following Java code produces a digital signature that can be verified using Chilkat RSA.  Links to the Chilkat signature verification examples follow this code.  The Java signature creation code does not use Chilkat to produce the digital signature.  It also demonstrates how to save a generated key (public and private) to DER files that can be used with Chilkat RSA.

import java.io.*;
import java.security.*;

// Chilkat is only used for Base64 and Hex encoding.
import com.chilkatsoft.*;

public class SignTest {

  static {
    try {
        System.loadLibrary("chilkat");
    } catch (UnsatisfiedLinkError e) {
      System.err.println("Native code library failed to load.\n" + e);
      System.exit(1);
    }
  }

  public static void main(String argv[])
  {
  	  try
  	  {
		KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA");
		System.out.println("Generated RSA Key!");
		generator.initialize(1024);
		KeyPair keyPair = generator.generateKeyPair();

		PrivateKey privKey = keyPair.getPrivate();
		PublicKey pubKey = keyPair.getPublic();

		// Save the private key to an ASN.1 DER file:
		byte[] privKeyDer = privKey.getEncoded();
		OutputStream outPrivKey = new FileOutputStream("privKey.der");
		outPrivKey.write(privKeyDer);
		outPrivKey.close();

		// Save the public key to an ASN.1 DER file:
		byte[] pubKeyDer = pubKey.getEncoded();
		OutputStream outPubKey = new FileOutputStream("pubKey.der");
		outPubKey.write(pubKeyDer);
		outPubKey.close();

		Signature _signature = Signature.getInstance("SHA1withRSA");
		_signature.initSign(privKey);

		// Sign the string "The quick brown fox jumps over the lazy dog"
		String strToSign = "The quick brown fox jumps over the lazy dog";
		byte[] bytesToSign = strToSign.getBytes();
		_signature.update(bytesToSign,0,bytesToSign.length);

        // If you signed a string with characters in non-English languages, you may
        // wish to see the exact bytes signed, perhaps by loading the following file
        // in a hex editor.  Make sure the program verifying the signature uses the same
        // byte representations for the characters (i.e. the same character encoding).
		OutputStream outBytesSigned = new FileOutputStream("bytesToSign.txt");
		outBytesSigned.write(bytesToSign);
		outBytesSigned.close();

		// Sign the contents of a file with this commented-out code:
		//FileInputStream fis = new FileInputStream("dude.gif");
		//BufferedInputStream bufin = new BufferedInputStream(fis);
		//byte[] buffer = new byte[1024];
		//int len;
		//while ((len = bufin.read(buffer)) >= 0) {
			//_signature.update(buffer, 0, len);
			//};
		//bufin.close();

		// Create the signature.
		byte[] sigBytes = _signature.sign();

		OutputStream out = new FileOutputStream("sig.dat");
		out.write(sigBytes);
		out.close();

		// Convert the signature to a Base64 or hex string:
		CkByteData ckSigBytes = new CkByteData();
    	ckSigBytes.appendByteArray(sigBytes);

	    //  Convert to hexidecimalized string:
	    System.out.println(ckSigBytes.getEncoded("hex"));

	    //  Convert to base64 string:
	    System.out.println(ckSigBytes.getEncoded("base64"));

		System.out.println("Success!");

	    //} catch (NoSuchProviderException e) {
	    //	System.out.println("NoSuchProviderException!");
	    } catch (IOException e) {
	    	System.out.println("IOException!");
	    } catch (InvalidKeyException e) {
	    	System.out.println("InvalidKeyException!");
		} catch (SignatureException e) {
			System.out.println("SignatureException!");
		} catch (NoSuchAlgorithmException e) {
	    	System.out.println("NoSuchAlgorithmException!");
			}

  }
}

Verify Digital Signature examples using Chilkat in various programming languages:
ASP: Verify Java Signature
SQL Server: Verify Java Signature
C#: Verify Java Signature
C++: Verify Java Signature
MFC: Verify Java Signature
C: Verify Java Signature
Delphi: Verify Java Signature
Visual FoxPro: Verify Java Signature
Java: Verify Java Signature
Perl: Verify Java Signature
PHP: Verify Java Signature
Python: Verify Java Signature
Ruby: Verify Java Signature
VB.NET: Verify Java Signature
Visual Basic: Verify Java Signature
VBScript: Verify Java Signature

Tomcat UnsatisfiedLinkError

If Java (running under Tomcat or any other environment) cannot load the Chilkat library, make sure the chilkat.dll and chilkat.jar are located in a directory listed in the java.library.path.

You can view the java.library.path in your environment by inserting this line of code:

System.out.println(System.getProperty(“java.library.path”))

Using SYSTEMTIME in Java

Chilkat methods that return date/time information do so using SYSTEMTIME. The reason is that Chilkat’s C++ API uses SYSTEMTIME (a MS Windows struct for holding date/time information) and these are wrapped to produce the Java (JNI) API.

Here is an example showing how to access the contents of SYSTEMTIME:

    CkEmail email = new CkEmail();
    
    SYSTEMTIME dt = new SYSTEMTIME();
    email.get_LocalDate(dt);
    
	int month = dt.getWMonth();
	int year = dt.getWYear();
	int day = dt.getWDay();
	int hour = dt.getWHour();
	int minute = dt.getWMinute();
	int second = dt.getWSecond();

Error: This application has failed to start because the application configuration is incorrect. Reinstalling application may fix this problem.

This error message is usually an indication that the VC++ runtime is missing on a system.

Downloading and installing the Microsoft VC++ runtime that matches the version you need will fix this problem.  To find the redistributable at microsoft.com, Google using this search string “visual c++ redistributable 2005”.  Substitute “2008”, “2002”, or “2003” for different versions…

For example, one recent Chilkat customer had this error message in Java:

java.lang.UnsatisfiedLinkError: C:\temp\new\chilkat.dll: This
application has failed to start because the application
configuration is incorrect. Reinstalling the application may fix this problem

The Chilkat modules/libs for Java, Perl, Python, and Ruby are compiled using Visual C++ 2005 (not SP1), so you would need the runtime for that version (i.e. VC++ 8.0).


This is the same error message in Czech:

Spustení této aplikace se nezdarilo, protoze konfigurace není správná. Tyto potíze lze pravdepodobne vyresit opakovanou instalací aplikace.