Clean code, stateless session beans and private state
Asked Answered
D

4

10

According to clean code by Robert C. Martin methods should have a small signature. The best case would be a method with no parameters at all. Instead it is recommended to use state variables. This is really useful. But what about stateless session beans?

The name is kind of confusing because SLSB can have state. You just have to do your housekeeping so you don't use state from the previous EJB call.

Getting back to clean code: I'd love to use instance variables in SLSBs too. This works fine and if you're careful enough you don't have any trouble with state inconsistencies since the state is overwritten on each public method call.

So far so good. But what happens if a used bean goes back to the pool? It takes its state with it. Depending on the size of the state this could be a real memory leak. JBoss is very generous with beans and generates quite a bunch of them causing some serious memory consumption - for nothing.

So one way would be to clean up the state before the bean method exists and the bean is returned to the pool. But this seems to me like useless code that should be avoided.

Is there a proper way to deal with this problem? What's the best practice in this situation?

Degrade answered 24/4, 2012 at 14:3 Comment(1)
Any state maintained by some DIY method will fail in the face of clustering, so it's not welcome for JEE. And maintaining a copy of that state for each bean also seems wrong to me.Pinion
A
1

Keep life simple, just pass in parameters. Even if you can do otherwise, it's obvious from the intention of a stateless EJB you shouldn't.

FWIW aiming for a goal of zero parameters seems silly to me. Aim for few, yes, but striving for zero for its own sake is just daft.

Adytum answered 24/4, 2012 at 14:7 Comment(4)
Actually I'm note very dogmatic about zero parameter methods. But I like to use a maximum of 2 parameters. I find methods with more then two parameters harder to read and to maintain. And from the OO-Model it perfectly makes sense to use state variables if cohesion is high.Degrade
That's all well and good, but taking a step back, let's acknowledge you're talking about putting personal cosmetic preference against adding state to what is really clearly a stateless bean. You need to balance OO principles with this, not just favour them blindly.Adytum
Btw a downvote seems harsh in response to a genuine opinion which just happens to not agree with the direction you seem to want to take your bean?Adytum
Fair enough sorry about that :-)Adytum
L
1

It's perfect possible to keep instance variables in SLSB, since you don't use the proxy do make calls between methods. For instance:

@Stateless 
public class MyEJB {
    private String myVar;

    public void receiveVar(String myVar) {
        this.myVar = myVar;
        useVar();
    }

    private void useVar() {
        // do something with var
    }
}

The point is: when you inject this SLSB in another, any method call will pass through the proxy to achieve the actual EJB. So, considering that the real instance is retrieved from the pool when the method is called on the proxy instance, there's no guarantee that the proxy will use the same pooled instance between two or more calls. So isn't possible ensure the value of any declared class attribute.

When the SLSB backs to the pool, it take with itself every setted value (I think it may change according the vendor, I'm not really sure). But, it's completely possible (and acceptable) that a pooled SLSB instance already has a previously configured attribute value.

I didn't understand your point here:

So far so good. But what happens if a used bean goes back to the pool? It takes its state with it. Depending on the size of the state this could be a real memory leak. JBoss is very generous with beans and generates quite a bunch of them causing some serious memory consumption - for nothing.

Do you have any example of "big state" you could have in a SLSB?

And finally:

I think the best way to handle the values is always handle state variables that you'll use. Setting before and cleaning after use. And the best practice is avoid this kind of confusing situation.

Hope it helps.

Leicestershire answered 21/6, 2016 at 12:31 Comment(0)
A
0

according to clean code by Robert C. Martin methods should have a small signature.

Usually i would prefer to pass in (transfer objects) as arguments, this way i can change what i pass in without affecting the method signature.

Also, i would prefer to pass in an interface, instead of the actual base class.

public void doSomething(IMyTransferObject arg){
 ...
}

Where IMyTransferObject is an interface

interface IMyTransferObject {
   ...
}

class TransferObject implements IMyTransferObject{
  private String name;
  private String game;
  ... accessor / mutator
}

The best case would be a method with no parameters at all. Instead it is recommended to use state variables. This is really usefull. But what about stateless session beans?

This can't be followed religiously, and there is no reason for doing so, really.

Andante answered 24/4, 2012 at 14:38 Comment(1)
That's a lot of code for internal private methods :) Actually I was talking about the private methods inside the SLSB.Degrade
A
0

From http://docs.oracle.com/javaee/6/tutorial/doc/gipjg.html:

Stateless Session Beans

A stateless session bean does not maintain a conversational state with the client. When a client invokes the methods of a stateless bean, the bean’s instance variables may contain a state specific to that client but only for the duration of the invocation. When the method is finished, the client-specific state should not be retained. Clients may, however, change the state of instance variables in pooled stateless beans, and this state is held over to the next invocation of the pooled stateless bean. Except during method invocation, all instances of a stateless bean are equivalent, allowing the EJB container to assign an instance to any client. That is, the state of a stateless session bean should apply across all clients.

I'm not an expert in EE, but this sounds to me that it is technically allowed to use fields the way you plan too.

I assume that you have to make sure that with every new method call, the instance fields are updated with the new data, and I think you should make sure you are removing the references after the method has ended to make sure you don't block the garbage collection of old objects just because they are referenced in some "old" bean that is still kept in some pool.

I would suggest a pattern like that:

public class MyBean{

  private SomeClass firstObject;
  private SomeOtherClass anotherObject;
  private AndAnotherClass thirdObject;

  public void theMethod(firstObject, anotherObject, thirdObject){
    try {
      this.firstObject = firstObject;
      this.anotherObject = anotherObject;
      this.third = thirdObject;

      startProcessing();

    }finally {
      this.firstObject = null;
      this.anotherObject = null;
      this.third = null;
    }
  }

  private void startProcessing() {
    doStep1();
    doStep2();
    doStep3();
  }

  [...]
}

Still a lot of code - but if you stick consistently to that style, you automatically skip the "theMethod" part and continue reading at "startProcessing", where you have everything cleanly and without parameters.

Autogenous answered 10/12, 2013 at 16:57 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.