Getting started with JACOB. An Example with Source Code

UPDATED: 28 December 2013
JACOB Library + jacob-project
The JACOB Project
JACOB stands for JAva COM Bridge. The JACOB project started in 1999 by Dan Adler. It allows java programs to make native calls to system. JACOB supports on window x86 and x64 based native call.

Well its very useful library, however there are very few support article available on internet. We'll first understand basic java program that uses JACOB library and interacts with windows program that allows COM bridge support.

What JACOB actually do?
JACOB creates ActiveXObject of program identified using Program ID, Version independent Program ID or CLSID (Class ID aka Globally Unique Identifier) Read more about How to find CLSID or Program ID of program?

First Program With JACOB
package javaQuery.jacob;

import com.jacob.activeX.ActiveXComponent;
import com.jacob.com.Dispatch;
import com.jacob.com.LibraryLoader;
import com.jacob.com.Variant;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;

/**
 * @author vicky.thakor
 * @date 28th December, 2013
 * http://sourceforge.net/projects/jacob-project/
 * First Program to understand how to use JACOB library
 */
public class JACOBGettingStarted {

    public static void main(String[] args) {
        /**
         * `System.getProperty("os.arch")`
         * It'll tell us on which platform Java Program is executing. Based on that we'll load respective DLL file.
         * Placed under same folder of program file(.java/.class).
         */
        String libFile = System.getProperty("os.arch").equals("amd64") ? "jacob-1.17-x64.dll" : "jacob-1.17-x86.dll";
        try {
            /* Read DLL file*/
            InputStream inputStream = jacobExample.class.getResourceAsStream(libFile);
            /**
             *  Step 1: Create temporary file under <%user.home%>\AppData\Local\Temp\jacob.dll 
             *  Step 2: Write contents of `inputStream` to that temporary file.
             */
            File temporaryDll = File.createTempFile("jacob", ".dll");
            FileOutputStream outputStream = new FileOutputStream(temporaryDll);
            byte[] array = new byte[8192];
            for (int i = inputStream.read(array); i != -1; i = inputStream.read(array)) {
                outputStream.write(array, 0, i);
            }
            outputStream.close();
            /**
             * `System.setProperty(LibraryLoader.JACOB_DLL_PATH, temporaryDll.getAbsolutePath());`
             * Set System property same like setting java home path in system.
             * 
             * `LibraryLoader.loadJacobLibrary();`
             * Load JACOB library in current System.
             */
            System.setProperty(LibraryLoader.JACOB_DLL_PATH, temporaryDll.getAbsolutePath());
            LibraryLoader.loadJacobLibrary();

            /**
             * Create ActiveXComponent using CLSID. You can also use program id here.
             * Next line(commented line/compProgramID) shows you how you can create ActiveXComponent using ProgramID.
             */
            ActiveXComponent compCLSID = new ActiveXComponent("clsid:{00024500-0000-0000-C000-000000000046}");
            /*ActiveXComponent compProgramID = new ActiveXComponent("Excel.Application");*/

            System.out.println("The Library been loaded, and an activeX component been created");
            
            /**
             * This is function/method of Microsoft Excel to use it with COM bridge.
             * Excel methods and its use can be found on
             * http://msdn.microsoft.com/en-us/library/bb179167(v=office.12).aspx
             * 
             * Understand code:
             * 1. Make Excel visible
             * 2. Get workbook of excel object.
             * 3. Open 1test.xls1 file in excel
             */
            Dispatch.put(compCLSID, "Visible", new Variant(true));
            Dispatch workbook = compCLSID.getProperty("Workbooks").toDispatch();
            Dispatch.call(workbook, "Open", new Variant("D:\\test\\test.xls"));

            /* Temporary file will be removed after terminating-closing-ending the application-program */
            temporaryDll.deleteOnExit();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
Other Resources
1. JACOB Library
2. Microsoft Excel methods for COM bridge interaction
- For other Programs you've to Google it.

What's Next?
I'm gonna help you to learn How you can create your own DLL file for your customized system request and An applet example with source code. Well you've to wait for my next article. Subscribe to catch updates.

Other Resources:
Jacob + Visual Studio. Your custom .DLL to use in Java.

0 comments :


How to find CLSID or Program ID of program?

UPDATED:
Its very common for .Net guys but for Java Developer its hard as rocket science. I'm one of 'em until dig into it. This article for those who don't know how to find CLSID, Program ID and Version independent program ID.

All you need is one tool called OLE/COM Object Viewer by Microsoft. Its provided with Visual Studio but you don't have to download visual studio just to get OLE/COM Object Viewer. Its is standalone graphical utility which can be downloaded from free of cost.

Download : http://www.softpedia.com/get/System/System-Miscellaneous/OLE-COM-Object-Viewer.shtml

Step 1: You know what to do. Install it.

Step 2: Object Classes > All Objects

OLE/COM Object Viewer

Step 3: Find your program from hierarchy. Select application in right pane you'll find you required details.

OLE/COM Object Viewer

Its simple as that. All information you need to know about your program. Check out how you can interact with Windows program using java : Getting started with JACOB. An Example with Source Code



0 comments :


How to create Hibernate query log?

UPDATED: 23 December 2013

What is Hibernate?
Hibernate is framework that provides object oriented interaction with database. Now a days  it is used widely to handle large database.

If you are working behind large application which uses hibernate for all of its transaction, I think you might need to configure query log and tune up your hibernate criteria.

Use of hibernate with proper criteria/queries is like a life boat for application but amateur use of hibernate is like hole in life boat.

Problem: JOIN is one creates massive overload in hibernate criteria. To get your desired output you always use JOIN in your criteria. You should be careful while using JOIN in any of your hibernate criteria or queries (HQL).  Single JOIN will load tons of database records and create overhead on your application.

Why you need to configure query log?
For development purpose it will be very useful to track down each query execution through hibernate. I'm not talking about hibernate.show_sql property. It'll only show you query with ? but won't print actual input and output of that query.

We'll configure log4j to get input query parameter and output values. You should turn off this mechanism at production server of will create IO overhead on server.

Step 1: Creating log4j.properties file. I already created one for you all you need to do is place it in your project.
log4j.logger.org.hibernate=INFO
log4j.logger.org.hibernate.SQL=DEBUG
log4j.logger.org.hibernate.type=TRACE
log4j.logger.org.hibernate.hql.ast.AST=info
log4j.logger.org.hibernate.tool.hbm2ddl=warn
log4j.logger.org.hibernate.hql=debug
log4j.logger.org.hibernate.cache=info
log4j.logger.org.hibernate.jdbc=debug
log4j.rootLogger = DEBUG, FILE

# Define the file appender
log4j.appender.FILE=org.apache.log4j.DailyRollingFileAppender
# Set the DatePattern
log4j.appender.FILE.DatePattern='.'yyyy-MM-dd-HH-mm

# Set the append to false, should not overwrite
log4j.appender.FILE.Append=true

# Set the name of the file.
# It'll be created every minute with different filename(appnded with yyyy-MM-dd-HH-mm) and placed under log4j folder.
log4j.appender.FILE.File=log4j/QueryLog.log

# Define the layout for file appender
log4j.appender.FILE.layout=org.apache.log4j.PatternLayout
log4j.appender.FILE.layout.conversionPattern= %d{HH:mm:ss} %-5p %c - %m%n
Step 2: Configure this log4j.properties file before you perform any database transaction (Select, Insert, Update, Delete). Note: Download log4j [http://www.findjar.com/jar/log4j/jars/log4j-1.2.15.jar.html]
import org.apache.log4j.PropertyConfigurator; // import required
/** 
  * In below code I placed log4j.properties as string. 
  * Its file path, I placed log4j.properties in root directory/default package. You need to change path. 
  * If you are working with web application place it in war folder for below code to work.
  */
PropertyConfigurator.configure("log4j.properties");
Output:
17:43:45 DEBUG org.hibernate.SQL - select this_.UID as UID0_0_, this_.FIRSTNAME as FIRSTNAME0_0_, this_.Lastname as Lastname0_0_ from user_master this_ where this_.UID=?
17:43:45 TRACE org.hibernate.type.IntegerType - binding '1' to parameter: 1
17:43:45 DEBUG org.hibernate.jdbc.AbstractBatcher - about to open ResultSet (open ResultSets: 0, globally: 0)
17:43:45 TRACE org.hibernate.type.IntegerType - returning '1' as column: UID0_0_
17:43:45 TRACE org.hibernate.type.StringType - returning 'Vicky' as column: FIRSTNAME0_0_
17:43:45 TRACE org.hibernate.type.StringType - returning 'Thakor' as column: Lastname0_0_
As you can see it shows what is value of input parameter where this_.UID=? with binding '1' to parameter: 1 and return values of fired query.

Conclusion: We have to be very careful about what we are trying to fetch from database and what will be fetched by frameworks. So configure it in your application and tune it up!

0 comments :


java.lang.SecurityException: JVM Shared, not allowed to set security manager

UPDATED: 21 December 2013
Java, Applet
I created custom security manager for Applet to get all permission. In below code I'm allowing applet to exit and its not good practice but situation driving me that way for while. I'm also searching for better option. If you guys have solution please comment it.
class customSecurityManager extends SecurityManager{
    SecurityManager original;

    customSecurityManager(SecurityManager original) {
      this.original = original;
    }

    /** Deny permission to exit the VM(uncomment line).*/
    public void checkExit(int status) {
      //throw(new SecurityException("Not allowed"));
    }

    /* Allow this security manager to be replaced,in fact allow pretty much everything. */
    public void checkPermission(Permission perm) {
    }

    public SecurityManager getOriginalSecurityManager() {
       return original;
    }
}
It works pretty well in many systems but one system was throwing an exception as follow...
java.lang.SecurityException: JVM Shared, not allowed to set security manager
 at sun.plugin2.applet.SecurityManagerHelper.checkPermissionHelper(Unknown Source)
 at sun.plugin2.applet.AWTAppletSecurityManager.checkPermission(Unknown Source)
 at java.lang.System.setSecurityManager0(Unknown Source)
 at java.lang.System.setSecurityManager(Unknown Source)
 at SecurityApplet.init(SecurityApplet.java:103)
 at com.sun.deploy.uitoolkit.impl.awt.AWTAppletAdapter.init(Unknown Source)
 at sun.plugin2.applet.Plugin2Manager$AppletExecutionRunnable.run(Unknown Source)
 at j ava.lang.Thread.run(Unknown Source)
After doing lots of search over internet and trying different options finally found solution for applet. Loading applet in separate JVM did the job.
<applet>
...
<param name="separate_jvm" value="true">
...
</applet>

0 comments :


java.lang.IllegalStateException: More than the maximum number of request parameters (GET plus POST) for a single request ([512]) were detected.

UPDATED: 12 December 2013

This is very unusual error thrown by Jboss server. Error it self explain that you are passing more than 512 parameters in request. Which is not good practice but if situation drives you in that way. There is solution available for it.

"To change this limit, set the maxParameterCount attribute on the Connector." this message seems informative but actually its wrong message in case of JBoss 7 or may be in future versions.

Error message you've
java.lang.IllegalStateException: More than the maximum number of request parameters (GET plus POST) for a single request ([512]) were detected. Any parameters beyond this limit have been ignored. To change this limit, set the maxParameterCount attribute on the Connector.
 org.apache.tomcat.util.http.Parameters.addParameter(Parameters.java:199)
 org.apache.tomcat.util.http.Parameters.processParameters(Parameters.java:383)
 org.apache.tomcat.util.http.Parameters.processParameters(Parameters.java:229)
 org.apache.catalina.connector.Request.parseParameters(Request.java:2874)
 org.apache.catalina.connector.Request.getParameter(Request.java:1291)
 org.apache.catalina.connector.RequestFacade.getParameter(RequestFacade.java:363)
 javax.servlet.http.HttpServlet.service(HttpServlet.java:754)
 javax.servlet.http.HttpServlet.service(HttpServlet.java:847)
Solution:
We need to use org.apache.tomcat.util.http.* library to solve this error. You don't need to import or download this library. It already available in Jboss. All you need to increase value of Parameter Count.

Jboss 7
Step 1: Open standalone.xml file available in "jboss7\standalone\configuration" folder.
Step 2: Paste below code after </extensions> tag and change value as per your requirement.
<system-properties>
   <property name="org.apache.tomcat.util.http.Parameters.MAX_COUNT" value="2000"/>
</system-properties>
Jboss 6 or lower (I didn't try but it has to work in lower version of Jboss as suggested by informative message)
Step 1: Open standalone.xml file available in "jboss6\standalone\configuration" folder.
Step 2: Find connector tag same as follow and add maxParameterCount attribute.
<connector name="http" protocol="HTTP/1.1" scheme="http" socket-binding="http" maxParameterCount="1000" /> 

0 comments :


com.jacob.com.ComFailException: Can't get object clsid from progid

UPDATED: 03 December 2013
JACOB + jacob-project

Exception Stacktrace:
com.jacob.com.ComFailException: Can't get object clsid from progid
 at com.jacob.com.Dispatch.createInstanceNative(Native Method)
 at com.jacob.com.Dispatch.(Dispatch.java:99)
 at com.jacob.activeX.ActiveXComponent.(ActiveXComponent.java:58)
ActiveXComponent comp = new ActiveXComponent("ABCXYZ");
This exception thrown by JACOB library when you try to create ActiveXComponent. Its coming because you are trying to create ActiveXComponent of program that is not installed in your system.


Solution:
You need to find proper CLSID or ProgID or VersionIndependentProgID for your program. Lets create Microsoft Excel's ActiveXComponent
ActiveXComponent comp = new ActiveXComponent("clsid:{00024500-0000-0000-C000-000000000046}");
ActiveXComponent comp = new ActiveXComponent("Excel.Application.14");
ActiveXComponent comp = new ActiveXComponent("Excel.Application");
1. Create ActiveXComponent using CLSID.
2. Create ActiveXComponent using version specific program id.
3. Create ActiveXComponent using version independent program id.

If you want to find CLSID or ProgID or VersionIndependentProgID for your program. Download OLEViewer and browser Object Classes > All Objects


OLEViewer


0 comments :


GWT (Google Web Toolkit) review

UPDATED: 02 December 2013
GWT(Google Web Toolkit) project started by Google back in 2005 - 2006. Its an open source set of tools that allows web developers to build Javascript front-end applications in Java. It is licensed under the Apache License version 2.0. Now its enough talk about its history. Today will give review of GWT from level of programmer.

What drives me to write good part of GWT?
The only things I observed for good part of Google Web Toolkit. If there is something do comment for other viewer.

  • It converts whole front-end website in complex JavaScript code. Thats the best part of Google Web Toolkit. It create bunch of complex JavaScript code that event hard for you to understand. 
  • Provide table, tree structure and other stuff by just writing 30-40 lines of code. 

What drives me to write bad part of GWT?
Yeah, I'm eagerly waiting for this part to write. Only by converting front-end website into JavaScript doesn't mean its good for develop small or large application.

Web security
Converting front-end website into JavaScript not only thing provide security to website. Security always depends on quality code. Properly handled validation leads to secure website.

Hard to understand (Time Consumption Factor)
Its very hard for new developer to understand its flow. You need to train your developer for Google Web Toolkit. Can't find help on Google also.

Pain for developer (Time Consumption Factor)
Its my personal experience that sometime just for CSS change you've to compile whole code.

- You can't access localhost website running in eclipse from other machine. You need to compile and create war and have to up in server. [In JSP, Servlet, Struts, etc... you can access localhost website running in eclipse from other system directly. Not required to compile and up it in server]

- You can't use all java package at client level. Check link to see which class supported by Google Web Toolkit http://www.gwtproject.org/doc/latest/RefJreEmulation.html#Package_java_io

- In some case GWT store cache in browser and website stops working and throws unexpected errors. You need to clean history of browser to let it work.

- To use some library you have to configure tons of thing in it. To use simple JSON library you have to waste more than 2-3 hours. Sometime works and sometime compilation error for just JSON. So you can imagine how hard to use external libraries.

- Last but not least. You can't use jQuery directly.


Conclusion
I would recommend not to use Google Web Toolkit at all. Even Google is not using GWT for their wide range of products. You may find very rare companies working on GWT.

@Developer: Don't do Job or Work for GWT.
@Manager, @Company: Just throw GWT and start working on other technologies. That may save your time and can work on other features for your product.

0 comments :