Monday, July 22, 2013

Different behaviour of Source or (dot) or (period) operator when passing arguments in Linux and Solaris

The source operator is used for including another file in current script and execute the lines in that file in the current shell context. Therefore the final result is same as that the lines in the sourced file were physically presented in the parent file. I recently found out that the behavior of source operator is different in Linux and Solaris.
If you pass command line arguments to a file you are sourcing inside another shell script, and when you retrieve the passed command line arguments in child (sourced) file,

In Linux,
You will get the parameters you passed as command line parameters when you sourcing the file.

In Solaris,
You will get the command line parameters passed to the parent file as the command line parameters for the child file also.

Therefore if you have a file named test.sh with following lines, (testEcho.sh will echo all the command line arguments passed to it).

. "./testEcho.sh" ted
sh ./testEcho.sh ted


and if you execute it like below,
sh ./test.sh param1 param2 param3


Output in linux,
ted
ted

Output in Solaris,
param1 param2 param3
      ted

Saturday, July 20, 2013

How to get Java system properties and JVM flags of a running Java process - Using jinfo

I wanted to check the current system properties and JVM flags of a Weblogic managed server, so I first used "wlst" (Weblogic scripting tool) to access that managed server. It was a little time consuming task and you need to have a knowledge about the inside of Weblogic server. But later I found out about this jinfo tool. jinfo is a very useful tool for retrieving Java system properties and JVM flags (JVM command line flags)  (and changing values of JVM flags) of a running local Java process or a remote server process. It was lot easier than accessing these properties using "wlst" or "jconsole". According to the "jinfo" documentation, This tool can also be used to get system properties and JVM flags of a remote server process.

But I am going to focus only about how to get those details of a local Java process in a Linux environment.
You can get the process ID of the specific process by doing a command like below in Linux. (Please replace "managed1" with a word (main class name, for example) in the command used for starting the Java process.)

ps -ef | grep "managed1"

In the output of above command, you can get the PID of the relevant Java process.
Then execute the following command. Please replace <PID> with the actual PID of the process.(I am assuming that path to JDK bin folder is in PATH environment variable).

jinfo <PID>

It will attach to the process related to that PID and will show the Java system properties and JVM flags like below.

Attaching to process ID 25965, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 11.0-b17
Java System Properties:

java.vendor = Sun Microsystems Inc.
org.xml.sax.parser = weblogic.xml.jaxp.RegistryParser
sun.java.launcher = SUN_STANDARD
com.sun.xml.ws.api.streaming.XMLStreamReaderFactory.woodstox = true
sun.management.compiler = HotSpot Tiered Compilers
os.name = Linux
sun.boot.class.path = /opt/jdk1.6.0_11/jre/lib/resources.jar:/opt/jdk1.6.0_11/jre/lib/rt.jar...
weblogic.threadpool.MinPoolSize = 50
java.vm.specification.vendor = Sun Microsystems Inc.
.....
VM Flags:

-Dweblogic.Name=managed1 ..................
...................... 
   
Other features of this tool:
(I didn't have a chance to experiment with these yet):
1. Get only JVM flags of the relevant Java process.
jinfo -flags <PID>
2. Get only Java system properties
jinfo -sysprops <PID>
3. Get a value of a specific JVM flag of the relevant Java process.
jinfo -flag <JVM_FLAG_NAME> <PID>
4. Change the value of a specific JVM flag of the relevant Java process.
        a) Enabling  a boolean JVM flag,
         jinfo -flag +<JVM_FLAG_NAME> <PID>
        b) Disabling  a boolean JVM flag,
         jinfo -flag -<JVM_FLAG_NAME> <PID>
        c) Setting a value of a JVM flag
         jinfo -flag  <JVM_FLAG_NAME>=<NEW_VALUE> <PID>

If you get VMVersionMismatchException,

Sometimes you may get following VMVersionMismatchException. 

Attaching to process ID 6461, please wait...
Exception in thread "main" java.lang.reflect.InvocationTargetException
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        at java.lang.reflect.Method.invoke(Method.java:597)
        at sun.tools.jinfo.JInfo.runTool(JInfo.java:79)
        at sun.tools.jinfo.JInfo.main(JInfo.java:53)
Caused by: sun.jvm.hotspot.runtime.VMVersionMismatchException: Supported versions are 17.1-b03. Target VM is 20.5-b03
        at sun.jvm.hotspot.runtime.VM.checkVMVersion(VM.java:223)
        at sun.jvm.hotspot.runtime.VM.<init>(VM.java:286)
        at sun.jvm.hotspot.runtime.VM.initialize(VM.java:350)
        at sun.jvm.hotspot.bugspot.BugSpotAgent.setupVM(BugSpotAgent.java:594)
        at sun.jvm.hotspot.bugspot.BugSpotAgent.go(BugSpotAgent.java:494)
        at sun.jvm.hotspot.bugspot.BugSpotAgent.attach(BugSpotAgent.java:332)
        at sun.jvm.hotspot.tools.Tool.start(Tool.java:163)
        at sun.jvm.hotspot.tools.JInfo.main(JInfo.java:128)
        ... 6 more

The reason for this is, you are using a "jinfo" tool related to a different java version than the JVM used to start this targeted process. If you get above exception, please find the JDK home of the JVM used for the targeted process, and use the "jinfo" tool in the bin folder of that JDK home.

According to the jinfo tool documentation, it seems this is not a standard tool of the JDK. In the documentation, there is a note saying
"NOTE - This utility is unsupported and may or may not be available in future versions of the JDK. In Windows Systems where dbgent.dll is not present, 'Debugging Tools for Windows' needs to be installed to have these tools working. Also the PATH environment variable should contain the location of jvm.dll used by the target process or the location from which the Crash Dump file was produced.
For example, set PATH=\jre\bin\client;%PATH%
"

How to avoid "java.lang.NoClassDefFoundError: Could not initialize class" when using JFreeChart in a headless server

Recently I encountered following exception when using JFreeChart to generate a graphical chart in a product deployed in a weblogic server.

]] Root cause of ServletException.
java.lang.NoClassDefFoundError: Could not initialize class sun.awt.X11GraphicsEnvironment
        at java.lang.Class.forName0(Native Method)
        at java.lang.Class.forName(Class.java:169)
        at java.awt.GraphicsEnvironment.getLocalGraphicsEnvironment(GraphicsEnvironment.java:68)
        at sun.awt.X11.XToolkit.(XToolkit.java:89)
        at java.lang.Class.forName0(Native Method)
        at java.lang.Class.forName(Class.java:169)
        at java.awt.Toolkit$2.run(Toolkit.java:834)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.awt.Toolkit.getDefaultToolkit(Toolkit.java:826)
        at sun.swing.SwingUtilities2$AATextInfo.getAATextInfo(SwingUtilities2.java:126)
        at javax.swing.plaf.metal.MetalLookAndFeel.initComponentDefaults(MetalLookAndFeel.java:1556)
        at javax.swing.plaf.basic.BasicLookAndFeel.getDefaults(BasicLookAndFeel.java:130)
        at javax.swing.plaf.metal.MetalLookAndFeel.getDefaults(MetalLookAndFeel.java:1591)
        at javax.swing.UIManager.setLookAndFeel(UIManager.java:541)
        at javax.swing.UIManager.setLookAndFeel(UIManager.java:581)
        at javax.swing.UIManager.initializeDefaultLAF(UIManager.java:1343)
        at javax.swing.UIManager.initialize(UIManager.java:1432)
        at javax.swing.UIManager.maybeInitialize(UIManager.java:1420)
        at javax.swing.UIManager.getDefaults(UIManager.java:660)
        at javax.swing.UIManager.getColor(UIManager.java:702)
        at org.jfree.chart.JFreeChart.(JFreeChart.java:261)
        at org.jfree.chart.ChartFactory.createTimeSeriesChart(ChartFactory.java:1918)
 

 Reason:
During the issue investigation, I found out that the above mentioned Weblogic server is located inside a headless server. (A headless server is a server which does not have a monitor, a key board and a mouse. The control and access to a headless server is done using a network card (remote connection).) It turned out the reason for the above exception is that.

The problem happens because JFreeChart class has some static variables which are initialized using local graphic environment properties retrieved from javax.swing.UIManager.
javax.swing.UIManager in turn tries to get these default properties from local graphic environment.
But because there is no graphic environment in a headless server , initializing sun.awt.X11GraphicsEnvironment class (local graphic environment class) fails and then the loading of JFreeChart class also fails.

Solution:
The solution for this problem is to add -Djava.awt.headless=true to the list of server start arguments of the managed server.  You can change it by,
  1. Login to the Weblogic admin console.
  2. Expand Environment and select Servers.
  3. In the Servers table, click the name of the managed server you want to configure.
  4. Select Configuration > Server Start.
If this is another server or some other java application, you can add this property to wherever place you can specify the JVM arguments for the start of that server or application.



Read more about Java headless mode from: http://www.oracle.com/technetwork/articles/javase/headless-136834.html

Friday, June 21, 2013

How to solve "javax.naming.CommunicationException [Root exception is java.net.ConnectException" thrown when connecting to a EJB in weblogic server

Recently during a test done on an EJB, I got the following exception.

javax.naming.
CommunicationException [Root exception is java.net.ConnectException: t3://server01:7101: Bootstrap to server01/10.10.58.26:7101 failed. It is likely that the remote side declared peer gone on this JVM]
javax.naming.
CommunicationException [Root exception is java.net.ConnectException: t3://server01:7101: Bootstrap to server01/10.10.58.26:7101 failed. It is likely that the remote side declared peer gone on this JVM]
    at weblogic.jndi.internal.
ExceptionTranslator.toNamingException(ExceptionTranslator.java:40)
   ......

Caused by: java.net.ConnectException: t3://
server01:7101: Bootstrap to server01/10.10.58.26:7101 failed. It is likely that the remote side declared peer gone on this JVM
    at weblogic.rjvm.RJVMFinder.
findOrCreateInternal(RJVMFinder.java:216)
..............

    ... 25 more
Caused by: java.rmi.ConnectException: Bootstrap to
server01/10.10.58.26:7101 failed. It is likely that the remote side declared peer gone on this JVM
    at weblogic.rjvm.
ConnectionManager.bootstrap(ConnectionManager.java:334)
    at weblogic.rjvm.RJVMManager.
findOrCreateRemoteInternal(RJVMManager.java:254)
    at weblogic.rjvm.RJVMManager.
findOrCreate(RJVMManager.java:197)
    at weblogic.rjvm.RJVMFinder.
findOrCreateRemoteServer(RJVMFinder.java:238)
    at weblogic.rjvm.RJVMFinder.
findOrCreateInternal(RJVMFinder.java:200)
    ... 31 more

 It turned out that the reason for this exception is, the listen address (lets say "lstnr01") declared in the managed server in Weblogic Admin console is different from server name (although it is a correct address to that machine, I can use it to connect to weblogic console and do ssh) I used for initiating the connection to EJB. You can check the listen address of the server by browsing to "Environments"->Servers->YourServer->Configuration->General. In that page, there is a text box to enter "Listen Address".

Now after finding the reason for the problem, next problem I got is I cannot use this listen address "lstnr01" to connect to my machine, because that is not registered in a DNS server in the network. The mapping of "lstnr01" to that machine was only configured in the "/etc/hosts" file of the server.
Therefore to fix that issue, I added the same IP host name mapping entry to map "lstnr01" to server IP in the C:/Windows/system32/drivers/etc/hosts/hosts file.

10.10.58.26  lstnr01  

Then I executed the "ipconfig /flushdns" command using the command line. It refreshed the DNS cache of the local machine and updated the cache with newly added entry in the hosts file.
Then I used "lstnr01" as the remote server address instead of "server01" when connecting to the EJB.
 Then the above exception was gone and I was able to connect to the EJB and run the EJB method successfully.

How to highlight a searching text in "tail -f" output

When we are investigating an software issue of a software run on a unix machine, we normally use "tail -f" command to see the live log messages logged by the software (for e.g: checking managed server logs in a weblogic server). If you are looking the log for finding a specific log message, it will be easier if you can make the search word highlighted in some color in the output.

Following method is a one of way you can achieve that task. Please note that to write ^[ character, you should press Ctrl+V and then Ctrl+[

tail -f testEcho.txt | sed "s/\\(search\\)/^[[33;1m\\1^[[0m/g"

 



Wednesday, June 12, 2013

Writing a custom JUnit runner for running a single method using command line

Recently I needed to create a custom JUnit runner for executing a single method using the command line.  This is how I implemented that.


package testpackage;

import org.junit.internal.TextListener;
import org.junit.runner.JUnitCore;
import org.junit.runner.Request;
import org.junit.runner.Result;
import org.junit.runner.notification.RunListener;

public class SingleJUnitTestRunner {

    /**
     * Custom built junit runner for running single method.
     * Usage:
     * java -cp ...... testpackage.SingleJUnitTestRunner testpackage.TestClass#testMethod
     */
    public static void main(String... args) throws ClassNotFoundException {
        if (args.length == 0){
            System.out.println("Usage:");
            System.out.println("java -cp ...... testpackage.SingleJUnitTestRunner testpackage.TestClass#testMethod");
            System.exit(-1);
        }
        String[] classAndMethod = args[0].split("#");

        if (classAndMethod .length != 0){
            System.out.println("Usage:");
            System.out.println("java -cp ...... testpackage.SingleJUnitTestRunner testpackage.TestClass#testMethod");
                     System.exit(-1);
        }
        System.out.println("======================================");
        System.out.println("Test Execution started for " + classAndMethod[1] + " method in class " + classAndMethod[0] + ".");
        System.out.println("=====================================");

        Request request = Request.method(Class.forName(classAndMethod[0]),
                classAndMethod[1]);
        JUnitCore core = new JUnitCore();
        // Use the text listener to get the output from test cases to console
        RunListener listener= new TextListener(System.out);
        core.addListener(listener);
        Result result = core.run(request);


        System.out.println("RunCount: " + result.getRunCount());

        System.out.println("FailureCount: " + result.getFailureCount());
        System.out.println("IgnoreCount: " + result.getIgnoreCount());
        System.exit(result.wasSuccessful() ? 0 : -1);
    }

}

Tuesday, November 13, 2012

A JPA issue which was caused by the Oracle DB's treatment of empty strings in VARCHAR fileds as NULL

Yesterday I encountered a strange issue when I was doing a performance test of my current project using JMeter. My project uses EJB 3 on Weblogic 10.3 server and an Oracle 11g database. I executed a JMeter test with 25 threads with 4000 iterations. But on each test execution, the test cases failed with a UniqueConstraintException after running the test cases for about 10 minutes

That unique constraint violation exception happened because system was trying to insert a record which was already inserted to the database in setUpTest() method in JMeter java sampler client. But this was not supposed to happen because in actual test cases (in runTest() methods), the system runs a find query to check whether a record with matching value is already existing in the database before inserting any record of the specific type to the database. Another strange thing was this happened only to the test cases executed after the first 10 minutes of the test.

So after some investigation, I found that in the setUpTest() method, one field was set to an empty string in the specific entity object (record) I mentioned earlier. But when I checked the relevant record in the Oracle database, it contained NULL value instead of an empty string for the relevant field. 

After some googling, it turned out that when JPA (or using normal SQL query) insert a empty string to Oracle database, Oracle converts it to a NULL before storing it in the database. 

So the reason behind my issue is when JPA insert an entity object which has an empty string as the value for a its property, Oracle changes that field value to NULL and store NULL value in the database instead of an empty string. But in the JPA cache, the value of the relevant property of the inserted object is still an empty string, not a NULL value. When system runs the JPQL find query, it checks for the relevant object in the cache first. Because the relevant newly inserted object still has an empty string for the value of the relevant property, the find query returns that object, so system doesn't try to create a new object with the same values again. Therefore we don't get an unique constraint violation exception. But after about 10 minutes, the JPA cache expires and cache is reloaded from the database. At this time, the value for the previously mentioned field of the reloaded specific object is no longer an empty string, because what is in the database for that field is NULL. So from now on, when the system tries to find an object with a value of empty string for this field, it is no longer able to find it. Therefore it assumes this record doesn't exist in the database and tries to re-insert the record.  But because Oracle changes the empty string to NULL when it inserts the relevant record to the database and because a record with NULL already exists in the database, it throws an unique constraint violation exception.

See this discussion in stackoverflow for more details on why Oracle treats VARCHAR empty strings as NULL.

Friday, October 16, 2009

Customize ReCaptcha theme

ReCaptcha is a widely use Captcha generation web service which is owned by Google. Yesterday I had the opportunity to use ReCaptcha for one of my project. But there was a problem. Since ReCaptcha is generated to a certain style, width and height using a webservice request, it was hard to put it into the design of the form which I was trying to integrate ReCaptcha.
But finally I could solve the problem using some tricks. This is how I did it.
For using ReCaptcha, first you have to create an account ( account and service is free) in http://recaptcha.net/ and generate a public key and a private key for accessing ReCaptcha web service. You can choose two option when generating those keys, default is generated keys can only be used in provided ( when generating keys) web site. Other one is you can use generated keys in any server and you have to select the checkbox saying some global key enabling ( I can't remember it) for using this second option.
Then download the ReCaptcha library. It contains recaptchalib.php files and an example page. What do you want is recaptchalib.php. To use recaptcha, add following php codes in to the top of your php page.

require_once('recaptchalib.php');
$publickey = "your_public_key"; // get this from the signup page
$privatekey = "your_private_key";// get this from the signup page

Since you are looking for custom theme for ReCaptcha, add this javascript code to head section of the your php page.

<script type= "text/javascript">

var RecaptchaOptions = {
theme: 'custom',
lang: 'en',
custom_theme_widget: 'recaptcha_widget'
};

</script>

Value of "custom_theme_widget" which is 'recaptcha_widget' in above code is the name of the div which your recaptcha gadget will put into.
Then add a div with the above mentioned id 'recaptcha_widget' in to the place where you need your recaptcha. All other recaptcha related divs will reside in this created div. Add another div named 'recaptcha_image' inside 'recaptcha_widget' for holding the recaptcha image. You also need to add a input text field named 'recaptcha_response_field' for typing the letters in the captcha image. There are lot of other things you can put as your requirements as a link for audio recaptcha, for error messages, for refreshing recaptcha etc, and I'm not going to put all those things in my example. In addition to that, you also have to put code for getting recaptcha with your publick key (two parts of code, if javascript is disabled, there is an iframe to include).

So this is the code I finally got as ReCaptcha widget,
<div id="recaptcha_widget" style="display: none;">
<div id="recaptcha_image"></div>
<div class="recaptcha_only_if_incorrect_sol" style="color: red;">Incorrect please try again</div>
<span class="recaptcha_only_if_image">Enter the words above:</span>
<span class="recaptcha_only_if_audio">Enter the numbers you hear:</span>
<input id="recaptcha_response_field" name="recaptcha_response_field" type="text">
<strong style="font-size: 10px;"><a href="javascript:void(0);">Get another CAPTCHA</a></strong>

<!--div class="recaptcha_only_if_image"><a href="javascript:Recaptcha.switch_type('audio')">Get an audio CAPTCHA</a></div><br />
<div class="recaptcha_only_if_audio"><a href="javascript:Recaptcha.switch_type('image')">Get an image CAPTCHA</a></div><br /><br />
<div><a href="javascript:Recaptcha.showhelp()">Help</a><br />
</div-->

<script type="text/javascript" src="http://api.recaptcha.net/challenge?k=<?php echo $publickey;?>&lang=en"></script>

<noscript>
<iframe src="http://api.recaptcha.net/noscript?k=<?php echo $publickey;?>&lang=en" height="200" width="500" frameborder="0"></iframe>
<textarea name="recaptcha_challenge_field" rows="3" cols="40"></textarea>
<input type="'hidden'" name="'recaptcha_response_field'" value="'manual_challenge'">
</noscript>

</div>

I commented out some fields I did not want to use in this code. After coding to this point, there was another problem came. That is the image generated by ReCaptcha is a standarad size of 300px X 57px. By adding a little css code, I could change the size of the recaptcha image as I wanted. I added following CSS code into the head section ( between head tags) of my php page.

<style type="text/css">
div#recaptcha_image > img{
height:46px;
width:240px;
}
</style>

This is the final output of the code.

Tuesday, September 1, 2009

Use uppercase letters for mysql data table names in Windows

When we developing mysql based applications, there is a good probability to developers develop the application on Windows OS and deploy it on a linux server or vice versa. MySQL supports both lowercase and uppercase letters for table names in unix enviroments, but when it came to Windows, the default MySQL configuration does not support upper case letters in table names. This becomes a big headache if you need to restore mysql database backups from windows environments to unix environments ( other way round is not quiet a problem since all table names becomes lowercase in Windows machines) during several times while development.

Today I found a solution for this case insensitvity of table names in MySQL servers on Windows environment. There is a mysql system variable called "lower_case_table_names" and it has set to 1 in default mysql configuration for Windows. 1 means only lower case table names are supported. For gaining the support for Both lower and upper case letters in table names, what you have to do is find relevant my.ini file for your MySQL installation and add the following line to the end of the file.
lower_case_table_names=2
Then restart the MySQL server. Now you will be able to create tables with names which include both upper-case and lower-case letters.

Related MySQL articles,
http://dev.mysql.com/doc/refman/5.0/en/identifier-case-sensitivity.html
http://dev.mysql.com/doc/refman/5.0/en/server-system-variables.html#sysvar_lower_case_table_names

Saturday, July 18, 2009

Searching a MySql database for a Value to find which tables contains it.

In my recent works, I needed to do a search for a some string value to find what are the tables contains that value. Although there are easy tools and methods which allows you to search for a value in a known field and known data table, I couldn't found a easy way to search for a value in a entire MySQL database. So i wrote this simple PHP script for accomplished that task. If somebody needs such functionality, they can use the script. Please change the database host, user name, password ( and database name ) according to your requirements.

This scripts helps to search a value in an entire mysql database. In main results page, it will displays the tables which contains the search value and what are the fields which contains the search value and number of occurences of the search value. By clicking on the number of results column value in the main results table, You can go to a page which displays the rows which contains the search value in relevant database table.

Download it from
http://heidisoft.com/sites/default/files/phpmysearch.zip
or
http://rapidshare.com/files/257172086/phpmysearch.zip