glassfish3 Posts

How To Fix Glassfish’s Exception “only one instance running in the cluster”

Recently ive met a new exception on my Glassfish 3.1 log file, here is the complete stack trace

[#|2014-10-09T13:22:09.248+0700|INFO|glassfish3.1.2|
org.shoal.ha.cache.command.load_request|_ThreadID=301;_ThreadName=Thread-2;|
Skipped Loading of 396544c17b8bbbc620000f9b2196 since there is only one instance running in the cluster.|#]

Because of this error, somehow im unable to do a session failover on my Glassfish.

Using asadmin get-health show that my instance are both healthy and alive

glassfish3>asadmin get-health
Enter the value for the clusterName operand> cluster1
instance1 started since Thu Oct 09 16:43:21 ICT 2014
instance2 started since Thu Oct 09 16:45:40 ICT 2014
Command get-health executed successfully.

but both instances started not at the same time.

So what i do is very simple, i restarted my cluster so both of my instances started at the same time. And somehow, my error is gone and i can do failover seamlessly.

restart glassfish cluster

Google+

A Weird Error At Glassfish, “Class [ java/lang/AutoCloseable ] not found.”

Today i’ve found a very weird error on my Glassfish 3.1, here is the complete stack trace

[#|2014-10-09T10:54:02.685+0700|SEVERE|glassfish3.1.2|global|_ThreadID=24;_ThreadName=Thread-2;
|Class [ java/lang/AutoCloseable ] not found. 
Error while loading [ class com.edw.dodol.service.MyService ]|#]

Im using SpringMVC and the error affect all my service classes, so somehow my application is unable to start.
After trying several solution, i found out that my JAVA_HOME variable are still pointing to a JDK6 version, while my application need at least JDK7.

Changing my JAVA_HOME variable into JDK7 solve this issue.

A very weird error actually, usually running an application under a different SDK version will create a “Major-Minor Version Exception”, but somehow i cant see that error anywhere :-(

Google+

How to Log X-Forwarded-For HTTP Header on Glassfish Application Server

Yesterday i was talking with my friend, on how Glassfish Application Server able to log the http request’s original user ip. Because my Glassfish is behind Apache ModProxy, so what is logging om my Glassfish’s access log file is my proxy’s ip address.

My apache modproxy ip is 192.168.56.102, while my original ip is 192.168.56.101. So im planning to see “192.168.56.101″ on my Glassfish access log instead of “192.168.56.102″ which is my proxy’s ip.

This is my Access Logging screenshot,

But before you do that, please make sure, you checked the Access Logging checkbox

And this is the result of my Glassfish’s Access Log File, which is located at, <glassfish installation folder>/glassfish/domains/domain1/logs/access

"192.168.56.102" "NULL-AUTH-USER" "20/Oct/2013:15:40:11 +0700" "GET // HTTP/1.1" 200 563
"192.168.56.102" "NULL-AUTH-USER" "20/Oct/2013:15:40:12 +0700" "GET // HTTP/1.1" 200 563
"192.168.56.102" "NULL-AUTH-USER" "20/Oct/2013:15:40:12 +0700" "GET // HTTP/1.1" 200 563
"192.168.56.102" "NULL-AUTH-USER" "20/Oct/2013:15:40:13 +0700" "GET // HTTP/1.1" 200 563
"192.168.56.102" "NULL-AUTH-USER" "20/Oct/2013:15:40:13 +0700" "GET // HTTP/1.1" 200 563
"192.168.56.102" "NULL-AUTH-USER" "20/Oct/2013:15:40:13 +0700" "GET // HTTP/1.1" 200 563
"192.168.56.102" "NULL-AUTH-USER" "20/Oct/2013:15:40:13 +0700" "GET // HTTP/1.1" 200 563
"192.168.56.102" "NULL-AUTH-USER" "20/Oct/2013:15:40:13 +0700" "GET // HTTP/1.1" 200 563

As you can see, what is written on my access log is my proxy ip address instead of my original address.

After spending some time researching, i found out that Apache ModProxy have an “X-Forwarded-For” http header which contain the original user’s ip address. So this is my new Access Logging Format, you can see me logging “X-Forwarded-For” header on the end of my new logging format.

%client.name% %auth-user-name% %datetime% %request% %status% %response.length% %header.X-Forwarded-For%

And this is my lates access log file, you can see my original ip at the end of every access log.

"192.168.56.102" "NULL-AUTH-USER" "20/Oct/2013:15:51:56 +0700" "GET // HTTP/1.1" 200 563 "192.168.56.101"
"192.168.56.102" "NULL-AUTH-USER" "20/Oct/2013:15:51:56 +0700" "GET // HTTP/1.1" 200 563 "192.168.56.101"
"192.168.56.102" "NULL-AUTH-USER" "20/Oct/2013:15:51:56 +0700" "GET // HTTP/1.1" 200 563 "192.168.56.101"
"192.168.56.102" "NULL-AUTH-USER" "20/Oct/2013:15:51:56 +0700" "GET // HTTP/1.1" 200 563 "192.168.56.101"
"192.168.56.102" "NULL-AUTH-USER" "20/Oct/2013:15:51:56 +0700" "GET // HTTP/1.1" 200 563 "192.168.56.101"
"192.168.56.102" "NULL-AUTH-USER" "20/Oct/2013:15:51:57 +0700" "GET // HTTP/1.1" 200 563 "192.168.56.101"
"192.168.56.102" "NULL-AUTH-USER" "20/Oct/2013:15:51:57 +0700" "GET // HTTP/1.1" 200 563 "192.168.56.101"
"192.168.56.102" "NULL-AUTH-USER" "20/Oct/2013:15:52:05 +0700" "GET // HTTP/1.1" 200 563 "192.168.56.101"

Hope it’d help others, have fun ;-)

Google+

Executing EJB3 Using Glassfish 3 AppClient

On my last EJB3 tutorial, im still using the old fashioned way of EJB3. Still importing lots of jars, which is very dangerous due to the fact that sometimes i forgot which jar i need to include.

That’s why now im trying to use one of Glassfish’s feature application, appclient. It can bundle all the libraries and dependencies your EJB client needed, so it save your time from including various Glassfish’s jars to your project.

Lets start with a very simple ejb interface class,

package com.edw.facade;

public interface ConnectionFacadeRemote {
    String sayHello(String string);
    int sayAge(int age);
}

And a simple main class,

package com.edw.main;

import com.edw.facade.ConnectionFacadeRemote;
import java.util.Properties;
import javax.naming.Context;
import javax.naming.InitialContext;
import org.apache.log4j.Logger;

public class Main {

    private Logger logger = Logger.getLogger(Main.class);
    
    private void connect() {
        try{
            Properties props = new Properties();
            props.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.enterprise.naming.SerialInitContextFactory");
            props.setProperty("org.omg.CORBA.ORBInitialHost", "localhost");
            props.setProperty("org.omg.CORBA.ORBInitialPort", "3700");
            
            InitialContext ctx = new InitialContext();
            ConnectionFacadeRemote connectionFacadeRemote = (ConnectionFacadeRemote) ctx.lookup("com.edw.facade.ConnectionFacadeRemote");
            logger.debug(connectionFacadeRemote.sayHello("edwin ")); 
            logger.debug("my age is " + connectionFacadeRemote.sayAge(12) + " years");
        }catch(Exception ex){
            logger.error(ex,ex);
        }
    }

    public static void main(String[] args) {
        Main tejbc = new Main();
        tejbc.connect();
    }
}

After you create all classes needed, you have to build your application into .jar.
Next is to pull all the jar needed for this EJB client application to run smoothly. First go to your Server glassfish’s bin folder located in your Server glassfish installation folder, in my PC it would be (C:\Program Files\glassfish-3.0.1\glassfish\bin). And execute the package-appclient command.

C:\Program Files\glassfish-3.0.1\glassfish\bin>package-appclient
Creating C:\Program Files\glassfish-3.0.1\glassfish\lib\appclient.jar

It would create a jar file, appclient.jar, which located in your glassfish lib installation folder.

Next is copy your appclient.jar into your client computers. Extract it, and execute appclient command. The appclient format would be, appclient -jar .

C:\Users\edw\Documents\appclient\appclient\glassfish\bin>appclient -jar "C:\Users\edw\Documents\NetBeansProjects\TestEJBClient\dist\TestEJBClient.jar"
Apr 19, 2012 6:28:03 PM com.sun.enterprise.transaction.JavaEETransactionManagerSimplified initDelegates
INFO: Using com.sun.enterprise.transaction.jts.JavaEETransactionManagerJTSDelegate as the delegate
2012-04-19 18:28:10,067 [Main] DEBUG com.edw.main.Main:22 - hello edwin
2012-04-19 18:28:10,072 [Main] DEBUG com.edw.main.Main:23 - my age is 24 years

You can see the server side’s source code here. And here is my netbeans project structure

Not too hard right ;-)

Google+

Clustering and Session Replication Using Glassfish 3.1

Sometimes we need to replicate sessions between clustered environment to make sure session failovers. In this tutorial im trying to clustered 2 Glassfish instances located in the same computer, create a simple webapps and try to see whether session in instance 1 replicated to instance 2. I dont know why but Glassfish 3.0 seems doesnt support clustering so im using Glassfish version 3.1 instead.

Lets start by starting Glassfish, go to /bin and start it from command promt by typing asadmin start-domain domain1.

After it started, go to Glassfish console from your browser. Glassfish console URL will be http://localhost:4848/. Login and start creating a cluster from Clusters menu.

Start your cluster,

congratulation, you have started your cluster. Lets see details from each instances,

it shows your instance’s http port.

To test our session replication, i create a simple web application using Netbeans 6.9.
First is a simple jsp file, index.jsp

<%@page import="java.util.Enumeration"%>
<%@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">

<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>JSP Page</title>
    </head>
    <body>
        <h1>Session Form</h1>

        <%
                    if (request.getParameter("sessionName") != null && request.getParameter("sessionValue") != null) {
                        HttpSession httpSession = request.getSession();
                        httpSession.setAttribute(request.getParameter("sessionName"), request.getParameter("sessionValue"));
                    }
        %>

        <form action="index.jsp" method="POST">

            your session name : <input type="text" name="sessionName" /> <br />
            your session value : <input type="text" name="sessionValue" /> <br />
            <input type="submit" />

        </form>

        <h1>Your Sessions</h1>

        <%
                    Enumeration sessionNames = session.getAttributeNames();
                    while (sessionNames.hasMoreElements()) {
                        String mySessionName = sessionNames.nextElement().toString();
                        String mySession = request.getSession().getAttribute(mySessionName).toString();
                        out.print(mySessionName+ " --> "+mySession + " <br />");
                    }
        %>

    </body>
</html>

And the most important is the web.xml configuration,

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
    <distributable id="sessionDistribute" />
    <session-config>
        <session-timeout>
            30
        </session-timeout>
    </session-config>
    <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>
</web-app>

Build it into a war app and deploy it to our clustered environment, always make sure the Availability option checked as enabled.

After you launch it, input some value to jsp page in instance1 and save it. It will save your values to a session.

open instance2′s jsp page and check whether your instance1′s session is there.

As you can see, your sessions from instance 1 is replicated and available from instance 2.

Have fun using Glassfish. :)

Google+