Monday 21 January 2013

RMI example with NetBeans

nbRMIoracle is the server and nbRMIoracleClient is the client.

There are two classes Compute.java and Task.java in the compute package. Both are used by the server and the client. The server ComputeEngine.java resides in the engine package.

nbRMIoracleClient project has the client package. There are two classesComputePi.java and Pi.java in the client package.
IMPORTANT NOTE: Copyright notice given below covers all the source code lines in this blog article.

Task.java
-------------
/* * Copyright (c) 1995, 2008, Oracle and/or its affiliates. All rights reserved. *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
* are met: *
 * - Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer. *
* - Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution. *
* - Neither the name of Oracle or the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission. *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */

package compute;

public interface Task {    
       T execute();
}
Task is an interface that has a single function execute() without params but returns the object with
the same Template type passed to it.


Compute.java:
--------------------
package compute;

import java.rmi.Remote;
import java.rmi.RemoteException;

public interface Compute extends Remote {
    T executeTask(Task t) throws RemoteException;
}

Compute java has a single function executeTask which has the param t of type Task.

ComputeEngine.java
---------------------------
package engine;
 
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;
import compute.Compute;
import compute.Task;

public class ComputeEngine implements Compute {

    public ComputeEngine() {
        super();
    }

    public T executeTask(Task t) {
        return t.execute();
    }

 

    public static void main(String[] args) {

        if (System.getSecurityManager() == null) {

            System.setSecurityManager(new SecurityManager());

        }

        try {

            String name = "Compute";

            Compute engine = new ComputeEngine();

            Compute stub =

                (Compute) UnicastRemoteObject.exportObject(engine, 0);

            Registry registry = LocateRegistry.getRegistry();

            registry.rebind(name, stub);

            System.out.println("ComputeEngine bound");

        } catch (Exception e) {

            System.err.println("ComputeEngine exception:");

            e.printStackTrace();

        }

    }

}

ComputeEngine implements the Compute interface.  So it implements the executeTask function.

executeTask function simply executes the execute() function of the Task that is passed to it as param.

The main function of ComputeEngine sets the security manager first then creates an instance of itself.  Then exports this object cast as Compute to the variable stub.  After this it locates registry and binds the name compute to the object stub.

To run this program you must first define the classpath as given below.

Secondly you must set the vm options as given below:

-Djava.security.debug=access,failure 
-Djava.security.manager
-Djava.security.policy="C:\Users\ars\Desktop\nbRMIoracle\src\engine\server.policy" 
-Djava.rmi.server.codebase=file:/C:\Users\ars\Desktop\nbRMIoracle\build\classes/
 
The OUTPUT:
-------------------
ComputeEngine bound

Pi.java
---------
package client;

import compute.Task;
import java.io.Serializable;
import java.math.BigDecimal

public class Pi implements Task, Serializable {

    private static final long serialVersionUID = 227L;

    /** constants used in pi computation */
    private static final BigDecimal FOUR =
        BigDecimal.valueOf(4); 

    /** rounding mode to use during pi computation */
    private static final int roundingMode =
        BigDecimal.ROUND_HALF_EVEN

    /** digits of precision after the decimal point */
    private final int digits 

    /**
     * Construct a task to calculate pi to the specified
     * precision.
     */
    public Pi(int digits) {
        this.digits = digits;
    }

    /**
     * Calculate pi.
     */
    public BigDecimal execute() {
        return computePi(digits);
    } 

    /**
     * Compute the value of pi to the specified number of
     * digits after the decimal point.  The value is
     * computed using Machin's formula:
     *
     *          pi/4 = 4*arctan(1/5) - arctan(1/239)
     *
     * and a power series expansion of arctan(x) to
     * sufficient precision.
     */
    public static BigDecimal computePi(int digits) {

        int scale = digits + 5;
        BigDecimal arctan1_5 = arctan(5, scale);
        BigDecimal arctan1_239 = arctan(239, scale);
        BigDecimal pi = arctan1_5.multiply(FOUR).subtract(
                                  arctan1_239).multiply(FOUR);
        return pi.setScale(digits,
                           BigDecimal.ROUND_HALF_UP);
    }

    /**
     * Compute the value, in radians, of the arctangent of
     * the inverse of the supplied integer to the specified
     * number of digits after the decimal point.  The value
     * is computed using the power series expansion for the
     * arc tangent:
     *
     * arctan(x) = x - (x^3)/3 + (x^5)/5 - (x^7)/7 +
     *     (x^9)/9 ...
     */  

    public static BigDecimal arctan(int inverseX,
                                    int scale)
    {
        BigDecimal result, numer, term;
        BigDecimal invX = BigDecimal.valueOf(inverseX);
        BigDecimal invX2 =
            BigDecimal.valueOf(inverseX * inverseX);

        numer = BigDecimal.ONE.divide(invX,
                                      scale, roundingMode);
 
        result = numer;
        int i = 1;
 
        do {
            numer =
                numer.divide(invX2, scale, roundingMode);
            int denom = 2 * i + 1;
            term =
                numer.divide(BigDecimal.valueOf(denom),
                             scale, roundingMode);

            if ((i % 2) != 0) {
                result = result.subtract(term);
            } else {
                result = result.add(term);
            }
            i++;
        } while (term.compareTo(BigDecimal.ZERO) != 0);
        return result;
    }
}

Pi implements task with the template type BigDecimal.  There are original comments in the code that provides sufficient info.  The crucial function is computePi which returns the BigDecimal value of Pi.

arctan is a utility function and used by the computePi.

    public static BigDecimal computePi(int digits) {
 
ComputePi.java
---------------------
package client
 
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.math.BigDecimal;
import compute.Compute;

public class ComputePi {

    public static void main(String args[]) {

        if (System.getSecurityManager() == null) {
            System.setSecurityManager(new SecurityManager());
        }

        try {
            String name = "Compute";
            Registry registry = LocateRegistry.getRegistry(args[0]);
            Compute comp = (Compute) registry.lookup(name);
            Pi task = new Pi(Integer.parseInt(args[1]));
            BigDecimal pi = comp.executeTask(task);
            System.out.println(pi);
        } catch (Exception e) {
            System.err.println("ComputePi exception:");
            e.printStackTrace();
        }
    }   
}

ComputePi sets theSecurity Manager first.  Then sets the stub name to the name var.  It gets the registry name from the program params.  It looks up the name in the registry and gets the interface compliant Compute object, comp.    It creates a Pitask task using the number of digits passes in the programs vars, 2nd var.  It runs the executeTask of the comp object.

 

To run this client program:  You must first run the server with success.

Namely it should write: ComputeEngine bound

Then you should specify the classpath as given below:

You should specify the vm options and arguments as below:

-Djava.security.debug=access,failure
 -Djava.security.manager
 -Djava.security.policy="C:\Users\ars\Desktop\nbRMIoracleClient\src\client\client.policy" 
 -Djava.rmi.server.codebase=file:/C:\Users\ars\Desktop\nbRMIoracleClient\build\classes/

The OUTPUT:
3.141592653589793238462643383279502884197169399
BUILD SUCCESSFUL (total time: 0 seconds)

The security issue:
------------------------
You must specify the security policy for the server and client seperately.  If you check the first picture in this blog article you will notice server.policy and the client.policy:

Server.policy:
-----------------
grant codeBase "file:/C:/Users/ars/Desktop/nbRMIoracle/src/-" {
    permission java.security.AllPermission;
};

grant codeBase "file:/C:/Users/ars/Desktop/nbRMIoracle/build/-" {
    permission java.security.AllPermission;
};

The location of the server.policy is specified in the vm options as below:
-Djava.security.debug=access,failure 
-Djava.security.manager
-Djava.security.policy="C:\Users\ars\Desktop\nbRMIoracle\src\engine\server.policy" 
-Djava.rmi.server.codebase=file:/C:\Users\ars\Desktop\nbRMIoracle\build\classes/

The first line produces debug info.  The third line specifies the location of the server policy.
The fourth line specifies where the binary executables reside.

Client.policy:
---------------
grant codeBase "file:/C:/Users/ars/Desktop/nbRMIoracleClient/src/-" {
    permission java.security.AllPermission;
};

grant codeBase "file:/C:/Users/ars/Desktop/nbRMIoracleClient/build/classes/-" {
    permission java.security.AllPermission;
};

 

Similar to the server:
-Djava.security.debug=access,failure
 -Djava.security.manager
 -Djava.security.policy="C:\Users\ars\Desktop\nbRMIoracleClient\src\client\client.policy" 
 -Djava.rmi.server.codebase=file:/C:\Users\ars\Desktop\nbRMIoracleClient\build\classes/

Be carefull, many difficulties related to RMI are not RMI related but the problems of specifying these VM options.  URL and simple dir specifications may cause large difficulties.  One simpleway to get around these is to use the policyTool that you can find in:

C:\Program Files\Java\jdk1.6.0_26\bin

Using this tool if you check the below policy:

C:\Program Files\Java\jre6\lib\security\java.policy

You may have a realistic idea of what your system does and how to specify the params.


Otherwise you will first get:

access denied (java.net.SocketPermission 127.0.0.1:1099 connect,resolve)

Then:

Server exception: java.rmi.ServerException: RemoteException occurred in server thread; nested exception is:

    java.rmi.UnmarshalException: error unmarshalling arguments; nested exception is:

    java.lang.ClassNotFoundException: compute.Compute

Cheers.

Ali R+

Thursday 17 January 2013

Access JSP Map Field Values Without Using Names - 2

This is an example that demonstartes the use of JAVA pointers in order to handle JSPs genericly with includes...

Please read the comments carefully.

Kind Regards.

Ali R+

fieldVar.java
-------------
package test;
/*
 * This is the super class from which all
 * the other classes must be extended.
 */
/**
 *
 * @author Ali R+ SARAL
 */
public class fieldVar {
    public static String val="";
}
ScreenInput3.java
------------------
<%@page import="java.util.*,java.io.*, test.*"%>
<%
 /*
 * This jsp is submitted by the source jsp.
 * It takes all the field name/value pairs
 * and puts them into a hashmap.
 * It puts this hashmap into the pagecontext as
 * an attribute.  It forwards to the source jsp at the end.
 */
/**
 *
 * @author Ali R+ SARAL
 */  
    Map<String, Object> map = new HashMap<String, Object>();//hashmap to hold the JSP map field name/val pairs
    for (Enumeration en = request.getParameterNames(); en.hasMoreElements();) {
        String name = (String) en.nextElement();
        String value = request.getParameter(name);
       
        fieldVar fv= new fieldVar();
        fv.val=value;
        map.put(name, fv); //put each JSP map field name and val into the hashmap
        System.err.println(name + "=" + request.getParameter(name));
    }
    pageContext.setAttribute("hm", map, pageContext.APPLICATION_SCOPE);  //put hashmap into the pageContext
    pageContext.forward("GZTKONA03.jsp");  //call the same JSP page
%>
GZTKONA03.jsp
-------------
<%@page import="java.util.*,java.io.*,test.*"%>
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
    "http://www.w3.org/TR/html4/loose.dtd"&gt;
<%    
/*
 * This is the source jsp.  In the initial run, this jsp inits the SEC field and
 * ScreenInput3.jsp is submitted.  The fields of this jsp are extracted and put into
 * a hashmap by ScreenInput3.jsp . ScreenInput3.jsp submits back to this GZTKONA03.jsp .
 * In the second and consequent runs,  the variable handle hashmap is taken and
 * manipulated without using variable names.
 */
/**
 *
 * @author Ali R+ SARAL
 */
    String[] fieldNames = new String[10];
    fieldNames[0]="SEC";
   
    fieldVar fv = new fieldVar();
    //fv.val="9";
    String messageVar="test msg";
    HashMap fieldvarMap=new HashMap();
    fieldvarMap.put("SEC", fv);
    
    HashMap fieldvalmap= (HashMap)pageContext.getAttribute("hm",4);
    
    if (fieldvalmap!=null)
         if (fieldvalmap.size()>0){
        System.out.println("hm not null not length 0");
       
        Object[] fields=fieldvalmap.keySet().toArray(); //get all the field names
        Object[] values=fieldvalmap.values().toArray(); //get all the field values
       
        System.out.print("\naccess the field vals by sequence");
        System.out.println("first field name="+fields[0]);
        fieldVar fv2 = (fieldVar) fieldvalmap.get(fields[0]); //get the value without using field name
        System.out.println("user entered first field val="+fv2.val);
        //fv2.val = "999";  //change the value without using field name
        System.out.println("user entered at end fv.val="+fv.val);
       
        System.out.print("\naccess the field vals by names written into the JSP");
        System.out.println("first static JSP field name="+fieldNames[0]);
        fieldVar fv3 = (fieldVar) fieldvalmap.get(fieldNames[0]); //get the value without using field name
        System.out.println("user entered first JSP field val="+fv3.val);
        fv3.val = "999";  //change the value without using field name
        System.out.println("\nprogrammatically changed to 999 at end fv3.val="+fv.val);
        System.out.println("fv.val changed indirectly at end fv.val="+fv.val);      
    }
       else {
    System.out.println("GZTKONA03.jsp is opened");
   
       } else fv.val="9";  //init the input field
%>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>Gazete Kontrol Programı Giriş</title>
    </head>
    <body>
        <h1>GAZETE KONTROL PROGRAMI 1. EKRANI</h1>
        <form name="myform" action="ScreenInput3.jsp" method="POST">
            <!--*S**     '1.CIP IRSALIYE GIRISI' /--><br>
            1.CIP IRSALIYE GIRISI<br>
            <!--*S**     '2.CIP ISTEK GIRISI' /--><br>
            2.CIP ISTEK GIRISI<br>
            <!--*S**     '3.STAND IRSALIYE GIRISI'/--><br>
            3.STAND IRSALIYE GIRISI<br>
            <!--*S**     '4.ON OFIS IRSALIYE GIRISI' ///--><br>
            4.ON OFIS IRSALIYE GIRISI<br>
            <!--*S** 'SECIM:'#SEC--><br>
            SECIM: <input type="text" name="SEC" id="SEC" value="<%=fv.val%>"/><br />
            <br />
            <br />
            <br />
            <div id='message' ><%=messageVar%> </div> 
        </form>
    </body>
</html>
<%   
    System.out.println("end of GZTKONA03 screen");
%>

Screens:
---------
First screen:
--------------

Second screen user entry before submit:
-----------------------------------------------

Third screen output:
------------------------


output:
-------
INFO: Grizzly Framework 1.9.31 started in: 0ms - bound to [0.0.0.0:8181]
INFO: end of GZTKONA03 screen
SEVERE: SEC=91
INFO: hm not null not length 0
INFO: access the field vals by sequence
INFO: first field name=SEC
INFO: user entered first field val=91
INFO: user entered at end fv.val=91
INFO: access the field vals by names written into the JSP
INFO: first static JSP field name=SEC
INFO: user entered first JSP field val=91
INFO: programmatically changed to 999 at end fv3.val=999
INFO: fv.val changed indirectly at end fv.val=999
INFO: end of GZTKONA03 screen

Tuesday 15 January 2013

Access JSP Map Field Values Without Using Names

The purpose of this short article is to access the JSP map field vars automatically without using their names.  I will first show how to access vars without using their names in JAVA, namely using JAVA pointers.  Then, in the next blog articles I will put this solution into use with JSP examples.

Cheers.

Ali R+

accessMapFieldValuesWithoutNames.java
-------------------------------------
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
import java.util.Vector;
/*
 * Purpose: To access JSP map field values automatically without using their names.
 *          We would like to access the values of the map fields by using pointers.
 *
 * Implementation :The key kere is to keep the field values in an object.  We put
 *               the object in a hashmap.
 */
/**
 *
 * @author Ali Riza SARAL
 */
public class accessMapFieldValuesWithoutNames {
    public static void main(String[] args) {
        Map<String, Object> hmVarHolder = new HashMap<String, Object>();  // create a hashmap to hold vars

        varClass var1 = new varClass();  // create an instance of var object
        var1.value = "var1Val";  // put a value into the new var
        System.out.println("initial var1 value=" + var1.value);
        hmVarHolder.put("var1", var1); //put the new var into the var holder
       
        //------------------------------------------------------
       
        varClass var2 = (varClass) hmVarHolder.get("var1"); // create a pointer to the var1
        System.out.println("var1.value copied to var2.value=" + var2.value); // var2 points at var1
        var2.value = "newVar2value";     // change the value of var2 /change the (pointed) value of the var2
        System.out.println("\nThe newly assigned var2.value=" + var2.value);
        System.out.println("The original value is changed by var2 ---> var1.name=" + var1.value); // the value of var1 changes also
        //------------------------------------------------------
       
        varClass var3 = (varClass) hmVarHolder.get("var1");
        System.out.println("var1.value copied to var2.value=" + var3.value); // var3 points at var1
        var3.value = "newVar3value";     // change the value of var3
        System.out.println("\nThe newly assigned var3.value=" + var3.value);
        System.out.println("The original value is changed by var3 ---> var1.name=" + var1.value); // the value of var1 changes also
        System.out.println("The var2 value is changed by var3 ---> var2.name=" + var2.value); // the value of var2 changes also
    }
    public static class varClass {
        String value = "";
    }
}
The output:
-----------
run:
initial var1 value=var1Val
var1.value copied to var2.value=var1Val
The newly assigned var2.value=newVar2value
The original value is changed by var2 ---> var1.name=newVar2value
var1.value copied to var2.value=newVar2value
The newly assigned var3.value=newVar3value
The original value is changed by var3 ---> var1.name=newVar3value
The var2 value is changed by var3 ---> var2.name=newVar3value
BUILD SUCCESSFUL (total time: 0 seconds)