venerdì 21 giugno 2013

Tricky session management

Session management is always a pain in the ass for the programmers.
Is never the case to say that it is easy.

With the introduction of the technology up to here spoken in this blog (EJB), we have a new way to manage user' session.

Let's see how.
This practice will work both in the case you want to develop a web application that uses a EJB as logic tier and in case you have a desktop application that uses the logic tier as business tier.

The trick consist in use a stateful session bean in order to keep active the session.

@Stateful(name="Login")
@Remote(IUser.class)
//@StatefulTimeout(value = 10, unit = TimeUnit.SECONDS)
@StatefulTimeout(value = 2, unit = TimeUnit.HOURS)
public class LoginManager 
implements IUser {
 private static Logger logger = Logger.getLogger(LoginManager.class);
 private Integer IdUtente;
....
....
    @Remove
    public void doLogout() {
     logger.info("distruggo la sessione e rimuovo l'EJB");
     this.IdUtente = null;
     
    }
    @PreDestroy
    private void myPreDestroy(){
     logger.info("PREDESTROY invalido la sessione e distruggo il bean");
     this.IdUtente = null;
     
    }
....
}
The method doLogin(String user, String password) is omitted because irrelevant for this scope.
In order to understand the trick, let's analyze the code from the top.

Stateful session beans, so the EJB container will handle itself the question to manage the user session. 
Remote, needed because we want to expose this methods via the public interface IUser.
Statefultimeout is used to keep active for a certain defined time the EJB. After this time is triggered, the ejb container (jboss/glassfish/whatever) will handle to remove the ejb.
Exaclty: the ejb will be removed, thus the user session will be invalidated.
Let's see the

  •  @remove notation. Indicates that the stateful session bean is to be removed by the container after completion of the method. 
  •  @predestroy notation. Goes hand in hand with remove, when the method marked with remove completes, the EJB container will invoke the method annotated with the @javax.annotation.PreDestroy annotation, if any, and then destroy the stateful session bean.


Remove is used to "remove" the bean after the method doLogout is called. 
Predestroy is used to invalidate the session, when the timer triggers the end of the session. Infact no one will call the doLogout method, but we want to invalidate anyhow the session.

Of couse the invalidation here means just put a variable to null, but you may want to perform more complicated actions. 

On the client side the session is maintained just keeping the pointer to the ejb handler. If the ejb has been removed on server side, using the stored handler will result in an exception. Thus the programmer will understand that the session is no more valid. 


sources:

martedì 18 giugno 2013

EJB smart lookup

I want to post a nice solution i found for looking up the EJB, easy and simple.
It follows the KISS idea, Keep It Simple and Strong.
Part of this solution is a contribution of Massimiliano.
Let's start from this idea:
I want to provide to the user a library that is capable to lookup enterprise beans, without telling him anything about the class that implements the exposed interfaces.

I have many enterprise beans in my application, one of the is for example the account manager:


import javax.ejb.Remote;
import javax.ejb.Stateless;
...
...
@Stateless(name = "Account")
@Remote(IAccount.class)

public class AccountManager implements IAccount {
...
}

This class implements the interface IAccount.  It is and EJB stateless bean, and the name used to look up this stateless bean is Account. Telling the name of the bean is the first step. Doing so we know the name we have to use for the lookup.
Once deployed the EJB projects an output like this:

java:global/MyBankLogicEAR/MyBankLogic/Account!main.IAccount
java:app/MyBankLogic/Account!main.IAccount
java:module/Account!main.IAccount
java:jboss/exported/MyBankLogicEAR/MyBankLogic/Account!main.IAccount
java:global/MyBankLogicEAR/MyBankLogic/Account
java:app/MyBankLogic/Account
java:module/Account


We need to consider the red part, to look up the EJB. Removing the name of the bean the red part would look like /MyBankLogicEAR/MyBankLogic/NameOfThePackage.AccountManager!main.IAccount

As already said, I want the user NOT to be aware of the path, the name and just avoid him all the problems of looking up the beans.

This said let's take a look at the code produced by Massimiliano:
final Hashtable jndiProperties = new Hashtable();
jndiProperties.put(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming");
try {
            final Context context = new InitialContext(jndiProperties);
            String appName = "";
            String moduleName = "jboss-firstbean";
            String distinctName = "";
            String beanName = "FirstBean";
            String interfaceFullName = "ejb.RemoteFirstBean";
            final String jndi = "ejb:" + appName + "/" + moduleName + "/" + distinctName + "/" + beanName + "!" + viewClassName;
            RemoteFirstBean statelessRemote = (RemoteFirstBean)context.lookup(jndi);

        } catch (NamingException ex) {
            System.out.println("problems");
        }
this is part of the post access EJB on jboss as 7. You may refer to it for more detailed explanations.
Thus this said, i want to avoid the user to use this snipped of code, but instead just tell which interface implementation he wants to lookup.
Interfaces are common among the client and the server, and shares the accessible remote methods. A part these methods, user must NOT be aware of everything else.

This is the solution i propose:
package utility;


import java.util.Hashtable;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;


public class Lookup<tipo>{

 private static final Hashtable jndiProperties = new Hashtable();
 private static final String appname = "MyBankLogicEAR";
 private static final String modulename = "MyBankLogic";
 private static final String distname = "";
 private static Context context;
 private Boolean isStateless = true;
 private String interfaceName = "";

 public Lookup(Boolean isStateLess, Class <Tipo> classe) {
  this.isStateless = isStateLess;
  this.interfaceName = classe.getName();
 }
 public <Tipo> Tipo lookup() throws Exception{
  Tipo res = null;
  String beanName = "";
  switch (interfaceName) {
  case "main.IAccount":
   beanName = "Account";
   break;
  case "main.ICliente":
   beanName = "Cliente";
   break;
  case "main.ICommonOperation":
   beanName = "Common";
   break;
  case "main.IDipendente":
   beanName = "Dipendente";
   break;
  case "main.IServizi":
   beanName = "Servizi";
   break;
  case "main.IUser":
   beanName = "Login";
   break;
  case "main.IReportGeneration":
   beanName = "Report";
   break;
  default:
   beanName = "";
   break;

  }
  if(beanName.compareTo("")==0){
   return null;
  }
  res = lookup(beanName, interfaceName, isStateless);
  return res;

 }

 private <Tipo> Tipo lookup(String beanName, String interfaceName,
   boolean stateless) throws Exception{
  jndiProperties.put(Context.URL_PKG_PREFIXES,
    "org.jboss.ejb.client.naming");
  Object bean;
  try {

   context = new InitialContext(jndiProperties);
   String jndi = "ejb:" + appname + "/" + modulename + "/" + distname
     + "/" + beanName + "!" + interfaceName;
   if (!stateless) {
    jndi = jndi + "?stateful";
   }
   //System.out.println("jndi: " + jndi);
   bean = context.lookup(jndi);
   return (Tipo) bean;
  } catch (NamingException ex) {
   throw new Exception("Non posso fare il lookup all'EJB");
  }
 }

}
In this way the user with a simple code like:
            
IUser  u = new Lookup<IUser>(Boolean.FALSE, IUser.class).lookup();
Can lookup the EJB which is responsible to provide the methods exposed in the interface IUser.


This is very simple because programmers on server side are aware of the names of the beans, and they may also write an even complex code for look up, like a factory does. Hence they can provide a simple library with this class to lookup the beans.
It is strong because user just knows whether or not an EJB is stateless or not, thus thanks to the interface and using the library it can lookup beans on the Jboss as 7 without having any problem with the name of the application, the EAR,  or the module name.

EJB 3 lifecycle

Today we will see how stateful and stateless bean does live their life, thus this will be used in another article in order to do a tricky session managment.

The lifecycle

We must distinguish between stateless session bean and stateful session bean because their lifecycle is different.

Before describing the difference in the lifecycle, let's recall the diffrerences between stateful and stateless:


  • Stateful
    they use class variables that are kept across the "conversation" between client and server (bean).
    Thus is possible to declare global variable in the class that implements the EJB, and theese variables are hold among the different requests of the client.
    When the client terminates there are two options to be undertaken: the bean is removed or session ends, thus state disappears.

    This kind of EJB are less scalable, wtr to the stateless. This is due to the overhead introduced by the need to keep the conversational state (memory on server side, methods called to maintain the EJB...).


  • Stateless
    They do not use class variables,  it will be useless because they die after the method call.

    They are throwaway enterprise beans. Thus by this feature their usage result in a more easy scalable application building. This type of beans can serve different clients at the same moment, without keeping track the about the session management. Hence there is no overhead for the server which is less stressed by the usage of this type of beans.

Let's take a look at the lifecycle now. Let's start by the latest one described above.


Stateless bean lifecycle
  • Stateless


    Stateless'bean lifecycle is described by the image here on the side.
    Very simply: 2 states for this state machine. The bean does not exist when is waiting to be called by the client. Once upon the bean is called it goes to the state ready. During this phase/state the bean can compute and perform the operation requested by the client through the remote method invocation. Hence once the method is terminated the bean goes back to does not exists.
    We can notice that there are:
    1. NO PASSIVATION
    2. NO ACTIVATION
Stateful bean lifecycle
  • Stateful

    Stateful beans add more than what the stateless offers. The basic concept remains the same.
    There are the does not exist state and the ready state, but further there is a state which is passive.
    This state is coming out from the need of maintaing the session, thus the variables. Once up on the bean is created is not destroyed when the first method invocation finishes, but is remains ready to satisfy other client requests. Anyhow the memory of the server may be used by other beans, or in general by other tasks, thus the bean is passivated and removed by the memory. From the oracle docs we can read "(Typically, the EJB container uses a least-recently-used algorithm to select a bean for passivation.) ".
    We can notice the need of:
    1. PASSIVATION. Used to move from the primary memory (ram probably) to a secondary memory on the server (cache, hard disk, raw memory)
    2. ACTIVATION. Used to bring back from secondary memory the bean, thus placing it in the primary memory ready to be called and serve the client.

Note that every step may be controlled through the annotation, we may for example want to run a task upon the Passivation or Activation of the bean, as well as when is Created or Removed.

We will see how to do a tricky session management with a stateful session bean in another article.



Sources:

Roseinda EJB tutotial session bean
docs oracle
image sources
roseinda
docs oracle






mercoledì 6 febbraio 2013

Enabling and using log4j on JBoss AS 7

Hi all,
today we will see how to enable and use log4j on JBoss as 7.
As you may already know JBoss comes already with his own version of log4j which is located under %jboss-home/modules/org/apache/log4j.


The following steps explains you what you have to do:
  1.  add the log4j.jar to your classpath, this may be done easly with the following steps
    • right click on your application - ejbmodule, Build path , configure build path..
    • then Add external jar, which you will find in the path mentioned above 
  2. Configure the logger. See below.
  3. Go the class you want to use the logger, suppose is in "mypackage.subpackage"
    add the import at the top of the class
    import org.apache.log4j.Logger;
  4.  create a field with the logger:
    private static Logger logger = Logger.getLogger(YourEJBClass.class);
  5. use the logger
    logger.info("started"); logger.debug("value of x" + x.toString());


Configure the logger

JBoss already comes with a configuration file under %Jboss-home/standalone/configuration/standalone.xml.
By default, your logger will output to server.log and console, but you can add some appender to output your app logs to another file.
Stop the server before start modifing the standalone.xml.
Log4j is highly customizable, here is a basic configuration:

<periodic-rotating-file-handler name="FILETWO">
  <formatter>
    <pattern-formatter pattern="%d{HH:mm:ss,SSS} %-5p [%c] (%t) %s%E%n"/>
  </formatter>
  <file relative-to="jboss.server.log.dir" path="mylogfile.log"/>
  <suffix value=".yyyy-MM-dd"/>
  <append value="true"/>
</periodic-rotating-file-handler>
This will be added in the standalone.xml, you can put it in the subsystem forlogging, after the CONSOLE one and the FILE one.

After this snippet of code, and before the <root-logger> node you can put the following snippet
<logger category="mypackage.subpackage">
    <level name="DEBUG"/>
    <handlers>
        <handler name="CONSOLE"/>
        <handler name="FILETWO"/>
    </handlers>
</logger>
Start again the server and enjoy your logging system.


sources: my original question at stackoverflow. Rafael answers and his blog