Showing posts with label Exception. Show all posts
Showing posts with label Exception. Show all posts

Saturday, July 20, 2013

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.

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.