• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Jeanne Boyarsky
  • Ron McLeod
  • Paul Clapham
  • Liutauras Vilda
Sheriffs:
  • paul wheaton
  • Rob Spoor
  • Devaka Cooray
Saloon Keepers:
  • Stephan van Hulst
  • Tim Holloway
  • Carey Brown
  • Frits Walraven
  • Tim Moores
Bartenders:
  • Mikalai Zaikin

Stateless EJB having statefull information

 
Greenhorn
Posts: 6
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi All,

I have written a stateless EJB using EJBGEN to generate the Home, remote & deployment descriptors. I am using weblogic 7.0.2 with jdk 1.3.1_02

The problem is that when I run my client.java to access the "Demo Stateless EJB" and call demoSelect() which returns i+1 on each call, I would expect that it would always be "1". This is because the Bean is stateless and does not have any information stored between to invocation.

But on each call I get the next number.
What's even more strange is when the client is run from different JVM's, I still get the next number in the sequence ...???

I am going mad.... Could someone please tell be why or point me in the right direction.

Thanks


I have included the code for anyone who may be interested.


import java.io.*;
import java.util.*;
import javax.naming.Context;
import javax.naming.InitialContext;


import ejb.demo.*;



public class Client
{
public static void main(String[] args) throws Exception
{
System.out.println("Creating InitialContext : " + new Date());
Context ic = new InitialContext();

System.out.println("Lookup : " + new Date());
DemoSSHome ssHome1 = (DemoSSHome) ic.lookup("sgs.DemoSSTest");
System.out.println("Create Home : " + new Date());
DemoSS ss1 = ssHome1.create();
System.out.println("Execute method : " + new Date());
System.out.println(ss1.demoSelect());

System.out.print("Hit <Ret> to continue...");System.in.read();


System.out.println("Lookup : " + new Date());
DemoSSHome ssHome2 = (DemoSSHome) ic.lookup("sgs.DemoSSTest");
System.out.println("Create Home : " + new Date());
DemoSS ss2 = ssHome2.create();
System.out.println("Execute method : " + new Date());
System.out.println(ss2.demoSelect());
System.out.println("Execute method : " + new Date());
System.out.println(ss2.demoSelect());

System.out.print("Hit <Ret> to continue...");System.in.read();




System.out.println("Lookup : " + new Date());
DemoSFHome sfHome1 = (DemoSFHome) ic.lookup("sgs.DemoSFTest");
System.out.println("Create Home : " + new Date());
DemoSF sf1 = sfHome1.create();
System.out.println("Execute method : " + new Date());
System.out.println(sf1.demoSelect());
System.out.println("Execute method : " + new Date());
System.out.println(sf1.demoSelect());
System.out.println("Execute method : " + new Date());
System.out.println(sf1.demoSelect());

System.out.print("Hit <Ret> to continue...");System.in.read();




System.out.println("Lookup : " + new Date());
DemoSFHome sfHome2 = (DemoSFHome) ic.lookup("sgs.DemoSFTest");
System.out.println("Create Home : " + new Date());
DemoSF sf2 = sfHome2.create();
System.out.println("Execute method : " + new Date());
System.out.println(sf2.demoSelect());
System.out.print("Hit <Ret> to continue...");System.in.read();


}
}




/**
* DemoBean -- This is implemented by the EnterPrise Bean author
*
* This class must extend javax.ejb.SessionBean and implement
* the methods in this interface as well as providing the
* implementation of the business methods.
*
* Note: this is the first time you have had to write any code
* so far everything else has had its implementation
* generated for you.
*/

package ejb.demo;

import javax.ejb.*;
import java.io.Serializable;
import java.util.*;
import java.rmi.*;

import javax.naming.*;

/**
* @ejbgen:session
* ejb-name = DemoSSBean
* type = Stateless
* max-beans-in-free-pool = 100
*
* @ejbgen:jndi-name
* remote = sgs.DemoSSTest
*
* @ejbgen:ejb-client-jar
* file-name = demo_client.jar
*/

public class DemoSSEJB implements SessionBean {
static final boolean verbose = true;

private SessionContext ctx;
private transient Properties props;
private int count = 0;

// Implement the methods in the SessionBean interface


public void ejbActivate() {
if (verbose)
System.out.println("Stateless ejbActivate called");
}

public void ejbRemove() {
if (verbose)
System.out.println("Stateless ejbRemove called");
}

public void ejbPassivate() {
if (verbose)
System.out.println("Stateless ejbPassivate called");
}

/**
* Sets the session context.
*
* @param SessionContext
*/
public void setSessionContext(SessionContext ctx) {
if (verbose)
System.out.println("setSessionContext called");
//this.ctx = ctx;
//InitialContext context = new InitialContext();

//props = (Properties) context.lookup("java:comp/env");
}


/**
* This method corresponds to the create method in the home interface
* "interfaces.DemoHome.java".
* The parameter sets of the two methods are identical. When the client calls
* <code>DemoHome.create()</code>, the container allocates an instance of
* the EJBean and calls <code>ejbCreate()</code>.r
*/
public void ejbCreate () {
if (verbose)
System.out.println("Stateless ejbCreate called");
}

/**
*
* ******* HERE IS THE BUSINESS LOGIC *************
* Do the demoSelect() here ==> don't even go to the database in this eg.
*
* @ejbgen:remote-method
*/
public String demoSelect()
throws RemoteException
{
count++;

return("SS : " + count);
}


/**
* Returns the JDBC pool name.
*
* @return string JDBC pool name
*/
// public String getDatabaseName() {
// return (String)props.get("jdbcPoolName");
//}


}
 
Ranch Hand
Posts: 90
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Stateless session beans are not necessarily destroyed between each method invocation; they are just returned to the session bean pool. That means that when a client invokes a method, it _might_ get the same bean that was used the last time the method was invoked. There's no way for the container to 'clear' the state of the bean instance between calls, so all instance variables remain the way they were when the method was invoked.

The key point here is that while stateless session beans _can_ have a 'state', in the meaning that they can have instance variables to use as they choose, this state is effectively useless. The same client might get two different beans for two sequential calls - its all up to the container.

The difference if you look to stateful beans is that a client _will_ get the same bean for sequential calls, which means that the internal state of the bean can be useful.
[ September 04, 2004: Message edited by: Mattias Arthursson ]
 
SivaKumar Kumar
Greenhorn
Posts: 6
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi Mattias,

Thanks for your reply.

I have now created a "statefull" session bean and used the lower half of the client bean (listed above), to test.

when I run two clients from different JVM's, I still get the next number in the sequence ...???. ie Each client appears to be sharing the same statefull session bean. I have "pause" statement in the client code to ensure that client 'A' does not finish before client 'B'.

Could someone please..please provide me with an explanation for this.

Thanks again in advance.


The statefull session bean is exactly the same as a stateless session bean.
The only difference being "type = Statefull".

I have listed it below just in case someone wants to have a look at it.



/**
* DemoBean -- This is implemented by the EnterPrise Bean author
*
* This class must extend javax.ejb.SessionBean and implement
* the methods in this interface as well as providing the
* implementation of the business methods.
*
* Note: this is the first time you have had to write any code
* so far everything else has had its implementation
* generated for you.
*/

package ejb.demo;

import javax.ejb.*;
import java.io.Serializable;
import java.util.*;
import java.rmi.*;

import javax.naming.*;

/**
* @ejbgen:session
* ejb-name = DemoSFBean
* type = Statefull
* max-beans-in-free-pool = 100
*
* @ejbgen:jndi-name
* remote = sgs.DemoSFTest
*
* @ejbgen:ejb-client-jar
* file-name = demo_client.jar
*/

public class DemoSFEJB implements SessionBean {
static final boolean verbose = true;

private SessionContext ctx;
private transient Properties props;
private int count = 0;

// Implement the methods in the SessionBean interface


public void ejbActivate() {
if (verbose)
System.out.println("StateFull ejbActivate called");
}

public void ejbRemove() {
if (verbose)
System.out.println("StateFull ejbRemove called");
}

public void ejbPassivate() {
if (verbose)
System.out.println("StateFull ejbPassivate called");
}

/**
* Sets the session context.
*
* @param SessionContext
*/
public void setSessionContext(SessionContext ctx) {
if (verbose)
System.out.println("setSessionContext called");
//this.ctx = ctx;
//InitialContext context = new InitialContext();

//props = (Properties) context.lookup("java:comp/env");
}


/**
* This method corresponds to the create method in the home interface
* "interfaces.DemoHome.java".
* The parameter sets of the two methods are identical. When the client calls
* <code>DemoHome.create()</code>, the container allocates an instance of
* the EJBean and calls <code>ejbCreate()</code>.r
*/
public void ejbCreate () {
if (verbose)
System.out.println("StateFull ejbCreate called");
}

/**
*
* ******* HERE IS THE BUSINESS LOGIC *************
* Do the demoSelect() here ==> don't even go to the database in this eg.
*
* @ejbgen:remote-method
*/
public String demoSelect()
throws RemoteException
{
count++;

return("SF : " + count);
}


/**
* Returns the JDBC pool name.
*
* @return string JDBC pool name
*/
// public String getDatabaseName() {
// return (String)props.get("jdbcPoolName");
//}


}
 
Greenhorn
Posts: 6
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
The problem is that you've put your count object as a global variable:

public class DemoSFEJB implements SessionBean {
static final boolean verbose = true;

private SessionContext ctx;
private transient Properties props;
private int count = 0;


instead you should write your demoSelect like so:

public String demoSelect()
throws RemoteException
{
int count = 0;
count++;

return("SF : " + count);
}

Then you should see the behavior expecting.

What's probably happening is that BEA is saving resources and caching the SessionBean.

Mark
 
SivaKumar Kumar
Greenhorn
Posts: 6
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi Mark,

By making the count a local variable, every call to the "statefull" session bean demoSelect method will always return "1". Even from the same Client session.

This is not the desired behavior. I would have expected the number to be incremental when called from the same client session.

Thanks
 
SivaKumar Kumar
Greenhorn
Posts: 6
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi

For anyone who may be interested.
EJBGen puts the session-type as "Stateless" if it cannot understand the doctag type = .....

I had put type = Statefull. note double 'll'.
 
reply
    Bookmark Topic Watch Topic
  • New Topic