To make your connection pooling optimal, you have to fetch and release a connection from the pool in every method of your ejb. The code is quite ugly and heavy.
I use a virtual proxy that catches the invocation of a method, and does pre and post processing, and forwards the method to the real implementation in between.
This is usefull for any object that should execute processing when a thread "enters" or leaves it.
In stateless session ejb context, this is very important because it will allow you to forward the execution of a session bean to a signleton object. The client information can be fetched from there, only if you published it somehow when the client entered the ejb.
remote interface (a little simplified):
interface SimpleDB extends EJBObject
{
String getValue(String key)
}
1) make a wrapper for your remote interface
class SimpleDBWrapper implements SimpleDB
{
SimpleDB wrappee;
String getValue(String key)
{
return wrappee.getValue(key)
}
}
2) make your EJB implementation entend the wrapper
this way, you can "plug" it's behaviour.
class SimpleDBEJB extends SimpleDBWrapper implements SessionBean
{
create() {} // <- todo
remove() {}
// ... ejb methods ...
}
3) implement your interface
(here one would make a connection, and do db stuff)
class MyImplementationSimpleDB implements SimpleDB
{
DataSoruce ds;
String getValue(String key)
{
Connection c = ds.getConnection();
PrepStat s = c.prepSta("select v from m where k=?");
s.bind(0,key);
ResultSet rs = s.execute();
String value = rs.next().getString(1);
c.close();
return value;
}
}
4) put that implentation in the bean during create()
class SimpleDBEJB extends SimpleDBWrapper implements SessionBean
{
create()
{
super.wrappee = new MyImplementationSimpleDB()
}
// ... ejb methods ...
}
note: using reflection and env, you can choose a behaviour (implementation class) at deploy time or even at session creation time = interesting: wrapper mechanism allows to make a layered implementation where each part (error checking, security checking, resolving, persistency) is programmed in a separate wrapper and all implementations are chained together).
5) now lets get to the point: the getConnection() and c.close() must be rewritten for many every method in the bean that needs to access the database: the same pre and post processing per method.
We could extend a wrapper and implement each method like
{
method()
{
pre(),
super.method(),
post();
}
}
I don't like that.
Trick: make an object that behaves like a wrapper where each method is implemented with the same pre and post processing.
class MethodProxy implements InvocationHandler
{
private Object forward;
public MethodProxy(Object forward_)
{
this.forward = forward_;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Exception
{
// ... pre processing...
try
{
// forward
return method.invoke(forward,args);
}
finally
{
// ...post processing...
}
}
// proxy factory
public Object proxy(Class class_)
{
Object virutal_proxy = Proxy.newProxyInstance(class_.getClassLoader(),new Class[]{class_},this);
return virutal_proxy;
}
}
now we put our old implementation in the forward of a proxy
SimpleDB forward = new MyImplementationSimpleDB()
MethodProxy method_proxy = new MethodProxy(forward)
SimpleDB proxy = method_proxy.proxy(SimpleDB.class)
The end result is a SimpleDB proxy that, when an external object invokes any method on it, it will first do pre processing, then it will execute the method (forward the call to our implementation) and afterward do post processing. When the implementation calls itself no pre or post processing will take place.
For EJB's this is really a big help, you can actually catch the event "a client enters the bean". You can use it to perform logging and debugging. I use it to allocate a connection from the pool, and release it. The problem is that there is no simple way to communicate the results of the pre processing to the real implementation that the method forwards to: how do i give the connection to the forward? I solved this by making a global map (singleton map) where i put(currentThread,connection). Since my persistency subsystem is a reentrant singleton, it's an evident sollution to have a mapping between thread and connection.
your input please!
and if you like it, what would you call it?
-
Method Wrapper (22 messages)
- Posted by: Dieter Cailliau
- Posted on: January 25 2002 04:43 EST
Threaded Messages (22)
- Method Wrapper by Bob Lee on January 25 2002 16:18 EST
- Method Wrapper by Nick Sanderson on January 29 2002 05:24 EST
-
Method Wrapper by Steve Chernyak on January 29 2002 09:55 EST
-
Method Wrapper by Dieter Cailliau on February 05 2002 08:57 EST
- Method Wrapper by Bob Lee on February 05 2002 10:03 EST
-
Method Wrapper by John Harby on February 19 2002 09:35 EST
- Method Wrapper by Dieter Cailliau on February 20 2002 05:24 EST
- Method Wrapper using AspectJ by Ron Bodkin on February 11 2002 02:37 EST
-
Method Wrapper by Dieter Cailliau on February 05 2002 08:57 EST
-
Method Wrapper by Steve Chernyak on January 29 2002 09:55 EST
- Method Wrapper by Vasantha Kumar on February 06 2002 23:19 EST
-
Method Wrapper by Dieter Cailliau on February 07 2002 04:56 EST
-
Method Wrapper by Dave Lorde on March 20 2002 06:30 EST
-
Method Wrapper by Dieter Cailliau on March 21 2002 03:37 EST
- Method Wrapper by Giedrius Trumpickas on April 04 2002 07:40 EST
-
Method Wrapper by Dieter Cailliau on March 21 2002 03:37 EST
-
Method Wrapper by Dave Lorde on March 20 2002 06:30 EST
-
Method Wrapper by Dieter Cailliau on February 07 2002 04:56 EST
- Method Wrapper by Nick Sanderson on January 29 2002 05:24 EST
- Method Wrapper by Rod Johnson on February 05 2002 18:51 EST
- Method Wrapper by Gabriel BECHARA on February 08 2002 10:50 EST
- Method Wrapper by Dieter Cailliau on February 11 2002 06:37 EST
-
Method Wrapper by Gabriel BECHARA on February 11 2002 08:04 EST
-
Method Wrapper by Dieter Cailliau on February 12 2002 03:51 EST
-
Method Wrapper by Gabriel BECHARA on February 12 2002 01:22 EST
-
Method Wrapper by Dieter Cailliau on February 13 2002 04:58 EST
-
Method Wrapper by Gabriel BECHARA on February 24 2002 12:22 EST
- Method Wrapper by Dieter Cailliau on February 25 2002 04:21 EST
-
Method Wrapper by Gabriel BECHARA on February 24 2002 12:22 EST
-
Method Wrapper by Dieter Cailliau on February 13 2002 04:58 EST
-
Method Wrapper by Gabriel BECHARA on February 12 2002 01:22 EST
-
Method Wrapper by Dieter Cailliau on February 12 2002 03:51 EST
-
Method Wrapper by Gabriel BECHARA on February 11 2002 08:04 EST
- Method Wrapper by Dieter Cailliau on February 11 2002 06:37 EST
-
Method Wrapper[ Go to top ]
- Posted by: Bob Lee
- Posted on: January 25 2002 16:18 EST
- in response to Dieter Cailliau
Decorator. -
Method Wrapper[ Go to top ]
- Posted by: Nick Sanderson
- Posted on: January 29 2002 05:24 EST
- in response to Bob Lee
I recently read the excellent article on aspect oriented programming published on this website. I followed the links through and tried out a few of the Xerox aspectj implementation examples.
Aspect oriented programming would seem to be a very good fit for solving this kind of problem. -
Method Wrapper[ Go to top ]
- Posted by: Steve Chernyak
- Posted on: January 29 2002 09:55 EST
- in response to Nick Sanderson
Is it correct to assume that most problems that require the use of dynamic proxies would be a good fit for using AOP? -
Method Wrapper[ Go to top ]
- Posted by: Dieter Cailliau
- Posted on: February 05 2002 08:57 EST
- in response to Steve Chernyak
AOP in short, is adding post and pre processing to groups of methods, where you define those groups using wildcards on the method names and the classes owneing the methods.
Since dynamic proxy is a way to catch OneClass.allmethods, you can simulate part of the behaviour of aspect stuff.
AOP is done mixed at compile time (your code is preprocessed and the aop code is intermingled in your code before compilation). -
Method Wrapper[ Go to top ]
- Posted by: Bob Lee
- Posted on: February 05 2002 10:03 EST
- in response to Dieter Cailliau
Actually, EJB is a domain-specific solution to the same problems AOP can (and will with a litte more maturity) solve. -
Method Wrapper[ Go to top ]
- Posted by: John Harby
- Posted on: February 19 2002 09:35 EST
- in response to Dieter Cailliau
"AOP is done mixed at compile time (your code is preprocessed and the aop code is intermingled in your code before compilation)."
But EJB involves compilation as well. -
Method Wrapper[ Go to top ]
- Posted by: Dieter Cailliau
- Posted on: February 20 2002 05:24 EST
- in response to John Harby
yes, in contradiction to dynamic proxies (reflection): runtime -> probably slower. -
Method Wrapper using AspectJ[ Go to top ]
- Posted by: Ron Bodkin
- Posted on: February 11 2002 14:37 EST
- in response to Steve Chernyak
AspectJ does indeed provide a clean, clear solution to many problems that use dynamic proxies.
For this example, you could write something like this:
public abstract class DBImplementation {
DataSource ds;
Connection c;
...
static aspect ManageConnections {
pointcut publicMethods() : execution(public * DBImplementation+.*(..));
before() : publicMethods() {
c = ds.getConnection();
}
after() : publicMethods() {
if (c != null) {
c.close();
c = null;
}
}
}
};
This allows any DB implementation that derives from DB implementation to manage connections. It cleans up even if the underlying method throws an exception and it is clear how the setup and tear down interact. It is also easier to handle a subset of methods and to use additional context to determine what to do.
-
Method Wrapper[ Go to top ]
- Posted by: Vasantha Kumar
- Posted on: February 06 2002 23:19 EST
- in response to Bob Lee
This is truly a decorator.Just to make my code look clean i wont do this much of processing.Moreover i think this also hampers maintainability of the code. -
Method Wrapper[ Go to top ]
- Posted by: Dieter Cailliau
- Posted on: February 07 2002 04:56 EST
- in response to Vasantha Kumar
i like clean code ass well, and i have a very clean mechanism to shift in a pre/post processing proxy. It's not because reflection is a little the edge of oo, that it can not be used clean.
But i'm very much interested in an alternative that is maintanable. I mean,
1) i don't want to code code (like adding pre() and post() in every method),
2) when i add a method i don't want to think about pre/post processing, how i did it, and if it will still work for my new method,
3) I even want to re-use my one pre/post-processor over many objects with different interfaces, i have good reasons for that.
So can you give me a clean construction that allows me to? -
Method Wrapper[ Go to top ]
- Posted by: Dave Lorde
- Posted on: March 20 2002 06:30 EST
- in response to Dieter Cailliau
If you don't mind generating lots of anonymous inner classes, what about the Template pattern?
In this case, you'd write a method (or a class with a method) that opens the connection, executes some SQL and closes the connection. Between the SQL execution and closing the connection, it calls a method on an action class that can process the SQL results. This action class is passed to the method along with the arguments for the SQL statement. For example:
public void executeQueryStatement(String sqlQuery, ResultSetProcessor rsp)
throws SQLException
{
Statement statement = null;
ResultSet resultSet = null;
try {
statement = connection.createStatement();
resultSet = statement.executeQuery(sqlQuery);
// Call action class to process results
rsp.processResultSet(resultSet);
}
finally {
if (resultSet != null) {
resultSet.close();
resultSet = null;
}
if (statement != null) {
statement.close();
statement = null;
}
connection.close();
}
}
The action class is just an abstract functor, for example:
abstract class ResultSetProcessor {
public void processResultSet(ResultSet resultSet)
throws SQLException;
}
The classes could be used like this:
...
String query = "select * from FOO where BAR='frab'";
new SQLManager().executeQueryStatement(query, new ResultSetProcessor() {
public void processResultSet(ResultSet resultSet)
throws SQLException {
if( resultSet.next() ) {
// process result
}
}
});
...
Just my 2 cents...
Dave
-
Method Wrapper[ Go to top ]
- Posted by: Dieter Cailliau
- Posted on: March 21 2002 03:37 EST
- in response to Dave Lorde
the good thing of this proxy-method-wrapper is that you don't have to repeat code in every method. If you use the template, you have to say "apply template(using this processor)" in every method. Unless you call the template from the proxy. Thus i think in a way you can see the proxy as the template, but the proxy is handy because it "intercepts" any method call, while the template can only be called in one way (unless you put a proxy in front etc :) -
Method Wrapper[ Go to top ]
- Posted by: Giedrius Trumpickas
- Posted on: April 04 2002 19:40 EST
- in response to Dieter Cailliau
I think it's typical aspect. Take a look at http://aspectj.org
-
Method Wrapper[ Go to top ]
- Posted by: Rod Johnson
- Posted on: February 05 2002 18:51 EST
- in response to Dieter Cailliau
I like the idea. Dynamic proxies are good decorators. I've just been looking at doing something similar.
The only catch is that <b>getting a dynamic proxy violates the EJB programming restrictions</b>. It's impossible to get a dynamic proxy without passing the current ClassLoader as an argument to Proxy.newProxyInstance(). However, the EJB specification states that "The enterprise bean must not attempt to create a class loader; obtain the current class loader...".
So I don't believe that this pattern is usable in the EJB tier. -
Method Wrapper[ Go to top ]
- Posted by: Gabriel BECHARA
- Posted on: February 08 2002 10:50 EST
- in response to Dieter Cailliau
You have
SimpleDBWrapper implements SimpleDB and SimpleDB that extends EJBObject
=> SimpleDBWrapper is a remote interface
then class SimpleDBEJB extends SimpleDBWrapper implements SessionBean
SimpleDBEJB is the IMPLEMENTATION (container side)
but it extends SimpleDBWrapper that implements SimpleDB and SimpleDB that extends EJBObject
=> SimpleDBEJB implement SessionBean (container side) AND EJBObject (remote or client side)
I do understand that you are trying to plug the behaviour of a remote interface in the EJB component
then you do
class MyImplementationSimpleDB implements SimpleDB (that extends EJBObject)
{
DataSoruce ds;
String getValue(String key)
{
( IT SEEMS LIKE PUTTING CODE IN THE REMOTE INTERFACE
IN EJB APPROACH YOU DO NOT IMPLEMENT AN INTERFACE IN THE OBJECT
BUT I UNDERSTAND, like I said before, YOU ARE DOING THIS IN ORDER TO plug the behaviour)
then you do class SimpleDBEJB extends SimpleDBWrapper implements SessionBean
AND AGAIN YOU HAVE A EJB component (container side) AND EJBObject (remote or client side)
EVEN IF YOU ARE DOING THIS IN ORDER TO plug the behaviour, in my opinion
IT IS NOT CLEAN AT ALL TO MIX REMOTE AND CONTAINER SIDE interfaces ????
YOU CAN DO THE SAME without mixing INTERFACES ?? You may loose what you call
plug the behaviour of a remote interface
BUT YOU WILL HAVE A CLEANER IMPLEMENTATION
MUCH MORE COMPONENT ORIENTED
WHEN YOU THINK PATTERNS YOU THINK CLEAN READABLE AND MAINTAINABLE CODE
-
Method Wrapper[ Go to top ]
- Posted by: Dieter Cailliau
- Posted on: February 11 2002 06:37 EST
- in response to Gabriel BECHARA
WHEN YOU THINK PATTERNS YOU THINK CLEAN READABLE
>> AND MAINTAINABLE CODE
I don't understand what you mean. I don't see the big problem about mixing those interfaces. What i do is this:
1) forget about ejb, just think java and object oriented:
2) i start with defining an interface: the interface of my "server": SimpleDB
3) i make an implementation which does the work: MyImplementationSimpleDB
that's all. Next, i realize ejb is cool because:
- it's a well defined standard to network-enable java objects,
- it allows to specify much at deploy-time (resources etc)
- it can manage transactions
so i start about thinking how i can make my object accessibler through ejb, without being dependent on ejb. I notice i have to add "extends EJBObject" to my SimpleDB, and i have to make an EJB object extending SessionBean. I certainly want my bean to do nothing except forwarding, because that will keep my implementation code really separated from ejb stuff. So first, i created an ejb which had a wrappee to forward every method to. In the next phase i realised the forwarding behaviour could be reused (to make a layered implementation) if i extracted it into a wrapper object. That's what i did, and that's why the ejb eventually extends the wrapper.
So, remember, the reason for this implementation is: the ejb is a layer on top of the real code, just to enable remote access and transactions in a simple way. I want to keep the real implementation separated from ejb stuff. But tomorrow a can throw away my ejb and "deploy" my component using another mechanism, without being scared that my code breaks, because i know very well what my ejb does: nothing, except transactions. The implementation is located in a simple java object.
I really don't think this approach is not component oriented. The EJB simply forwards it's requests to a java object, which is completely independant of the ejb system. The EJB is just a layer on top. The wrapper implementation class being the superclass of the ejb shoud not be confusing, it's just a trick to have automated default behaviour for my ejb. And also because a server implementation is often layered (my real implementation of my real SimpleDB is 5 wrappers together each doing part of the job).
-
Method Wrapper[ Go to top ]
- Posted by: Gabriel BECHARA
- Posted on: February 11 2002 08:04 EST
- in response to Dieter Cailliau
ABOUT CODE IN THE REMOTE INTERFACE :
If a developer managed to call directly the method which is implemented in the remote interface in:
class MyImplementationSimpleDB implements SimpleDB
{
DataSoruce ds;
String getValue(String key)
{
Connection c = ds.getConnection();
PrepStat s = c.prepSta("select v from m where k=?");
....
He can call the method getValue(...) (without a lookup for home and narrow for remote.) What will happen ?
He will connect directly to the database without passing by the container ??
And what about the security policy for the methods of the EJB?
It's BETTER to write some code without using EJB (using inheritance etc...
like you said: "forget about ejb, just think java and object oriented")
AND THEN wrap this code in EJB without mixing remote and implementation.
The EJB will be the wrapper and the methods will be accessible throught the remote interface where we put ONLY the method that are accessible remotely (with the appropriate policy )
-
Method Wrapper[ Go to top ]
- Posted by: Dieter Cailliau
- Posted on: February 12 2002 03:51 EST
- in response to Gabriel BECHARA
gabriel,
thanks for your advice. It's true that the construct allows bad programmers to hack without respecting the intention, because it's a kind of layered approach and one should spaeak to the top layer only. But there is no way for a programmer to reach the implementation object, so what's the problem? Only the ejb is "published" in jndi, and in the VM of the ejb, the implementation object is private, so no one can reach it.
Still explain me what do you mean when you say i am mixing remote and implementation? As i see it, you can talk about a client and a server, about an interface and implementation, and about ejb, but i don't understand what i'm doing wrong in your eyes, and it's about mixing. Tell me. -
Method Wrapper[ Go to top ]
- Posted by: Gabriel BECHARA
- Posted on: February 12 2002 13:22 EST
- in response to Dieter Cailliau
I am trying to get the point of what you are proposing but It's still is not clear for me.
Can you give me a clearer description of how to use this decorator pattern with the code relative to :
looking up in JNDI
getting the home
getting the remote reference
calling the remote methods
in this code
SimpleDB forward = new MyImplementationSimpleDB()
MethodProxy method_proxy = new MethodProxy(forward)
SimpleDB proxy = method_proxy.proxy(SimpleDB.class)
I cannot see where you get the remote object reference,
It seems like instantiating a local object ?
Is the method proxy of the class MethodProxy supposed to get a proxy of the remote object ?
And when you say :
"I solved this by making a global map (singleton map) where i put(currentThread,connection)"
you are talking about the thread of which object? (in EJB implementation you cannot use thread, the container
manages this for you)
Using the decorator pattern is quite useful in the context of code NOT involving the EJB interfaces.
But in the context of EJB it's seems confusing.
Using this pattern like you said will make, in my opininion, the code confusing ...
I do not really feel this approach is clean ... and elegant ...
This is my opinion. It may change once you give me a concrete example of using this pattern in the context of EJB.
Personally, I prefer to use the decorator pattern for implementing the classes that are not involved in the interfaces of the EJB (EJBObject or SessionBean )
then, if I needed the EJB, I wrap this code in a EJB ....
-
Method Wrapper[ Go to top ]
- Posted by: Dieter Cailliau
- Posted on: February 13 2002 04:58 EST
- in response to Gabriel BECHARA
i have not written any client code. The "proxy" has nothing to do with client side code. It's called proxy to indicate that it is a dynamic proxy. Every object i was talking about still resides at the server. The client lookup is traditional, like you described, using jndi.
When the container decides to create an ejb, it will instantiate (or ejbCreate) MySimpleDBEJB. The create() of that ejb was:
SimpleDB forward = new MyImplementationSimpleDB()
MethodProxy method_proxy = new MethodProxy(forward)
SimpleDB proxy = method_proxy.proxy(SimpleDB.class)
super.wrappee = proxy;
which is: forward any incoming method call to the dynamic proxy, which does the pre and post processing, and which forwards the method to the MyImplementationSimpleDB.
So, when a client does home.create(), the container makes the ejb, the ejb.create() makes the implementation object and pre/post-proxy, and finally, the result is an (ejb)->(pre/post-proxy)->(implementation) wrapped serie of SimpleDB's.
When the client invokes a method on the ejb, the ejb invokes it on the (pre/post-proxy), which does pre, invokes the method on it's wrappee (the implementation object) and after that, does post processing.
About threads; i believe it IS allowed to use the currentThread as a unique "key", it is not allowed to manage threads, but i don't see what's wrong with using the currentThread as key in a map. -
Method Wrapper[ Go to top ]
- Posted by: Gabriel BECHARA
- Posted on: February 24 2002 12:22 EST
- in response to Dieter Cailliau
I still do not agree with you for 2 points :
1-using the thread id of the instance of the EJB
of the container
is interfeering with the container management
of the bean. For example for entity beans
if option C is used then the same instance
which is pooled can be used for
another entity (another id for the same thread) ...
and entity beans ARE statefull session with
ore options ..
and when a session bean is pooled and then
reused for another puspose (in the case of multipurposes
business services) we cannot use it's
thread id in order to identify anything ?
2-About what I call mixing remote interfaces with
implementation ( that you call pugging in ...)
what if you wanded some of the methods to
be only accessed locally (local interfeces of ejb 2.0)
and others to be accessed remotely .
In this case your implementation should extend
the local or the remote interface ?
Plugging the behaviour is confusing a separation
is better even if you have to reenter the code ( some
tools do that for you)
-
Method Wrapper[ Go to top ]
- Posted by: Dieter Cailliau
- Posted on: February 25 2002 04:21 EST
- in response to Gabriel BECHARA
about threads, i simply believe it's ok. I'm talking about one method invokation to an ejb. I believe during one method invocation, it's ok to take the thread id. I think wathever is pooled by the container, the thread that executes one method invocation will be the same for the entire method execution. I'm just talking about this: a client calls a method A, the method A starts executing at the server, and there it takes the thread id to put some data in a (server--global data map. Next it passes execution to a shared object in the server's vm. That object is being accessed multi-treaded, and it looks up data in the global map, using the current thread as a key. Just before method A returns, the thread-data mapping is removed from the map.
About mixing interface and implementation; you're right that aspect-J would be nicer. I should give it a try. But i don't think my implementation is confusing. On the contrary, it's very clean. And very independant of ejb. I can run my system without using ejb's and i like that idea. I don't see how you can realize that, if you don't implement the functionality in a separate implemetation object.
We are not talking about local interfaces. I'm describing an ordinary server, it's not about an entity related to other entities.