Solution Details - TPI

Number 129506
Type TPI
Created Date 17-May-2005
Last Updated 25-May-2005
Title Using J-Link Methods In Servlets And JSP Running Under Tomcat With Java 2 Platform.
Details Additional Information

Description
-----------------
This document is written to provide a guideline for customers who intend to use J-Link methods under servlet engines (such as Tomcat) with Java 2 platform.

With Java 1.1 platform, it has been possible to use asynchronous-mode J-Link methods directly in Servlets and JSP. For example, the following JSP will successfully start Pro/ENGINEER under the combination of Tomcat 3.2.4 and JDK 1.1.8.

--------------------------------------------------------------------------------
<%@ page import="com.ptc.cipjava.*" %>
<%@ page import="com.ptc.pfc.pfcAsyncConnection.*" %>

<%

    System.loadLibrary("pfcasyncmt");
    
    AsyncConnection connection = pfcAsyncConnection.AsyncConnection_Start("proe1", null);
%>
--------------------------------------------------------------------------------

However, when Java 2 platform is used, the above JSP will cause UnsatisfiedLinkError at AsyncConnection_Start(). This is caused by a difference in how Java 2 class loaders work with JNI, related to Sun bug 4425434 at http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4225434.
JNI is "Java Native Interface", and it is the basis for how asynchronous J-Link communicates to Pro/TOOLKIT (and thus to Pro/ENGINEER).
Tomcat Release Note explains how to deploy JNI-based web applications.

    =======================
    JNI Based Applications:
    =======================
    Applications that require native libraries must ensure that the libraries have
    been loaded prior to use.  Typically, this is done with a call like:
    
      static {
        System.loadLibrary("path-to-library-file");
      }
    
    in some class.  However, the application must also ensure that the library is
    not loaded more than once.  If the above code were placed in a class inside
    the web application (i.e. under /WEB-INF/classes or /WEB-INF/lib), and the
    application were reloaded, the loadLibrary() call would be attempted a second
    time.
    
    To avoid this problem, place classes that load native libraries outside of the
    web application, and ensure that the loadLibrary() call is executed only once
    during the lifetime of a particular JVM.

JRE (and JDK) 1.4 is the supported Java version for Pro/ENGINEER Wildfire 2.0 (for more detailed information, see http://www.ptc.com/partners/hardware/current/jlink.htm). PTC recommends that users update their JRE to the minimum supported versions.
The Servlets and JSP that cause the UnsatisfiedLinkError by Java 1.1 dependent implementation must be revised to reflect the change mentioned above, in order to work under servlet engines (such as Tomcat) with Java 2 platform.


Alternate Technique
-----------------
See Resolution Below.


Resolution
-----------------
The following example explains the required procedures to build Servlets and JSP that invoke asynchronous-mode J-Link methods, running under Tomcat with Java 2 platform.

1. Copy pfcasync.jar to <Tomcat home directory>\shared\lib.

    Copy "pfcasync.jar" file, located in <Pro/ENGINEER load point>\text\java to <Tomcat home directory>\shared\lib


2. Create a Loader class.

    Create a "Loader" class, called JLinkLoader.class. This class will be used for the exclusive purpose of loading "pfcasyncmt". Below is the contents of JLinkLoader.java.    
    
--------------------------------------------------------------------------------
package example;

public class JLinkLoader {
    static {
        System.out.println("Loading library....");
        System.loadLibrary("pfcasyncmt");
        System.out.println("Done loading library....");
    }
}
--------------------------------------------------------------------------------

    (Note that everything except the loadLibrary() call is not required, and any package name could be used. "example" is used as the package name in this sample).

    Compile the JLinkLoader.java, and locate the class file in <Tomcat home directory>\shared\classes\example.

        <Tomcat home directory>\shared\classes\example>javac -classpath .;<Tomcat home directory>\shared\classes JLinkLoader.java


3. Build a web application directory.

    Build the following web application directory structure.

        <Tomcat home directory>\webapps\jlinkapp
        <Tomcat home directory>\webapps\jlinkapp\WEB-INF
        <Tomcat home directory>\webapps\jlinkapp\WEB-INF\classes
        <Tomcat home directory>\webapps\jlinkapp\WEB-INF\classes\bean


4. Create a Deployment class.

    Create a "Deployment" class called AsyncInstallTest.class, under the web application directory. This class has a static member of type JLinkLoader. Thus when this deployment class is loaded, JLinkLoader is as well and the library (=pfcasyncmt) will be loaded once. The method implemented in this class will be invoked by Servlets and JSPs. Below is the contents of AsyncInstallTest.java

--------------------------------------------------------------------------------
package bean;

import com.ptc.cipjava.*;
import com.ptc.pfc.pfcSession.*;
import com.ptc.pfc.pfcModel.*;
import com.ptc.pfc.pfcAsyncConnection.*;
import java.io.*;
import example.*;

public class AsyncInstallTest {

    private static JLinkLoader loader = new JLinkLoader();

    private static String proe_cmd = "";

    public static void main(String[] args) throws Exception {

        if (args.length != 1) {
            System.out.println("Wrong number of arguments");
            System.out.println("Usage: java AsyncInstallTest <Pro/ENGINEER startup command>");
            System.exit(1);
        } else {
            proe_cmd = args[0];
        }

        try {
            System.out.println("AsyncInstallTest started.");

            AsyncConnection ac = pfcAsyncConnection.AsyncConnection_Start(proe_cmd, null);

            Session currSession = ac.GetSession();
            Model model = currSession.CreatePart("AsyncInstallTest");
            model.Display();
            Thread.sleep(5000);         

            ac.End();

            System.runFinalization();

            System.out.println("AsyncInstallTest finished.");
            
        } catch (Throwable x) {
            System.out.println("Unexpected exception caught: " + x);
            x.printStackTrace();
        }
    }
}
--------------------------------------------------------------------------------

    Compile the AsyncInstallTest.java, and locate the class file in <Tomcat home directory>\webapps\jlinkapp\WEB-INF\classes\bean
    
		<Tomcat home directory>\webapps\jlinkapp\WEB-INF\classes\bean>javac -classpath .;<Pro/ENGINEER load point>\text\java\pfcasync.jar;<Tomcat home directory>\shared\classes AsyncInstallTest.java


5. Create a Servlet.

    Create a Servlet called ServletExample.class in <Tomcat home directory>\webapps\jlinkapp\WEB-INF\classes. Below is the contents of ServletExample.java.

--------------------------------------------------------------------------------
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
import bean.*;

public class ServletExample extends HttpServlet {

    public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {

        System.out.println("ServletExample started.");

        PrintWriter out = response.getWriter();
    
        out.println("<html>");
        out.println("    <body>");
        out.println(System.getProperty("java.library.path"));
        out.println("<br><br>");
        out.println(System.getProperty("java.class.path"));
        out.println("    </body>");
        out.println("</html>");
    
        String[] args = new String[1];
        args[0] = request.getParameter("proe_cmd");

        System.out.println("proe_cmd = " + args[0]);
    
        try {
            AsyncInstallTest.main(args);
        } catch (Exception e) {
            System.out.print(e.getStackTrace());
        }
    
        System.out.println("ServletExample finished.");
    }

    public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
    
        doGet(request, response);
    
    }
}
--------------------------------------------------------------------------------

    Compile the Servlet.

        <Tomcat home directory>\webapps\jlinkapp\WEB-INF\classes>javac -classpath .;<Tomcat home directory>\webapps\jlinkapp\WEB-INF\classes;<Tomcat home directory>\common\lib\servlet-api.jar ServletExample.java


6. Register the servlet in web.xml.
    
    Register the servlet in <Tomcat home directory>\webapps\jlinkapp\WEB-INF\web.xml. Here is an example of web.xml.

--------------------------------------------------------------------------------
<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
    version="2.4">

    <display-name>Using J-Link Methods In Servlets And JSP Running Under Tomcat With Java 2 Platform</display-name>
    <description>
        Using J-Link Methods In Servlets And JSP Running Under Tomcat With Java 2 Platform
    </description>
    
    <servlet>
        <servlet-name>servletexample</servlet-name>
        <servlet-class>ServletExample</servlet-class>
    </servlet>
    
    <servlet-mapping>
        <servlet-name>servletexample</servlet-name>
        <url-pattern>/servletexample</url-pattern>
    </servlet-mapping>
</web-app>
--------------------------------------------------------------------------------


7. Create a JSP.

    Create a JSP with the following contents. Name the JSP "jspexample.jsp", and locate the file in <Tomcat home directory>\webapps\jlinkapp

--------------------------------------------------------------------------------
<%@ page import="java.lang.Runtime.*" %>
<%@ page import="java.io.*"%>
<%@ page import="bean.*"%>
<hr>
<%
    out.println(System.getProperty("java.library.path"));
    out.println("<br><br>");
    out.println(System.getProperty("java.class.path"));
%>
<hr>
<%
    System.out.println("jspexample started.");
    
    String[] args = new String[1];
    args[0] = request.getParameter("proe_cmd");
    
    System.out.println("proe_cmd = " + args[0]);
    
    try {
        AsyncInstallTest.main(args);
    } catch (Exception e) {
        out.print(e.getStackTrace());
    }

    System.out.println("jspexample finished.");
%>
<hr>
Done!!
--------------------------------------------------------------------------------


8. Set system environment variables.

    Add the following paths in the system environment.

        <Pro/ENGINEER load point>\bin
        <Pro/ENGINEER load point>\i486_nt\lib

    Set PRO_COMM_MSG_EXE in the system environment.
    
        PRO_COMM_MSG_EXE=<Pro/ENGINEER load point>\i486_nt\obj\pro_comm_msg.exe

    Tomcat by default runs its service under the "System account". This means that it gets only the System variables, not local user variables. Therefore, user must have all the environment settings for asynchronous J-Link (paths to find the required libraries, and PRO_COMM_MSG_EXE) under the system environment variables.


9. Start Tomcat, and perform tests.

    [Servlet Test]
    
        Open a Web Browser and type the following URL. "proe1", used in the URL parameter is the Pro/ENGINEER startup command.

            http://<Host name>:8080/jlinkapp/servletexample?proe_cmd=proe1

        Pro/ENGINEER will be launched in the host machine where Tomcat is running. Pro/ENGINEER will be automatically terminated after 5 seconds. If it is the first attempt, the following messages will be displayed in Tomcat console window.

            ServletExample started.
            proe_cmd = proe1
            Loading library....
            Done loading library....
            AsyncInstallTest started.
            AsyncInstallTest finished.
            ServletExample finished.

        In case that pfcasyncmt library is already loaded in servlet engine by a previous attempt, the output will be like the following. The library is not loaded more than once due to the static member declaration of JLinkLoader in the deployment class (=AsyncInstallTest).

            ServletExample started.
            proe_cmd = proe1
            AsyncInstallTest started.
            AsyncInstallTest finished.
            ServletExample finished.

    [JSP Test]
    
        Open a Web Browser and type the following URL. "proe1", used in the URL parameter is the Pro/ENGINEER startup command.

            http://<Host name>:8080/jlinkapp/jspexample.jsp?proe_cmd=proe1

        Pro/ENGINEER will be launched in the host machine where Tomcat is running. If it is the first attempt, the following messages will be displayed in Tomcat console window.

            jspexample started.
            proe_cmd = proe1
            Loading library....
            Done loading library....
            AsyncInstallTest started.
            AsyncInstallTest finished.
            jspexample finished.

        If not the first attempt, the output will be like the following, as seen in the above servlet test.

            jspexample started.
            proe_cmd = proe1
            AsyncInstallTest started.
            AsyncInstallTest finished.
            jspexample finished.


Affected Products

Product Pro/ENGINEER
Module J-Link
Reported Release Wildfire 2.0
Reported Datecode Not Available
Resolved Release Not Available
Resolved Datecode Not Available
Affected Client All
Affected Server Not Available

Related Documents

Type Number Status Description

None Available