Am 13.12.2012 00:45, schrieb Denis Forveille:
Le 2012-12-12 18:27, Christian Beikov a écrit :
Sorry I mixed up your 3 emails a bit. Answers inline.
Am 13.12.2012 00:01, schrieb Denis Forveille:
This is the pattern defined by Seam 2 all the way and the assumption
on which it has been designed on first place...
I don't really understand your points, mostly I think because it
seems you describe patterns we don't use..
If you don't use "open session/entitymanager/connection in view" the
"patterns" I tried to describe are not so different from what I
understand about yours now.
At high level, our classes are organized like this :
- "Managers" classes in SLSB ("Event/ Scope/stateless..). Manager
provides generic function tied to a "business domain" (Customer,
orders) and deal with the database common access (get a "Customer"
list) or service (communicate with external systems)
Your Managers are all stateless then, did I get that right?
If so, this is what I meant by using something like application
scope, singleton or stateless so that's fine then.
As stated in my previous post, yes. Application or Singleton are not
that OK because you have to manage concurrent acess to methods in thos
beans. SLSB do that natively for us, and this very fast (SLSB are
pooled..)
If your managers are stateless you obviously have no shared state that
has to be protected by using synchronization constructs. The only thing
that is probably accessed concurrently is your EntityManager proxy.
Although the proxy already handles concurrency and you don't have to
take care of that anyway. If you are not using. Instances of your SLSBs
are accessed concurrently anyway, there happens no synchronization at
all(if it would be different i would not use stateless any more). The
pooling is nice, although I don't think that it will actually improve
performance. Since there are no declarative standard mechanisms like CMT
for simple POJOs yet, you definetly should use SLSBs for your managers.
My point was just that the lifetime of the beans in the mentioned scopes
would be "the same". Although it's not that simple but since you are
using SLSBs already anyway, stick to them.
- "Controllers" classes in SFSB either in View/Page or Conversation
scope. A controller is basically a JSF backing bean, handling one or
many (wizards) views. They can also access the databse (Very if this
customer already exist or can delegate this to a manager)
What I don't get is why you need SFSBs for your controllers. Why not
making them simple POJOs? Also in my opinion, letting the controllers
access the db directly is no good idea. Why not put these data access
methods into your managers or so?
Because the EJB Container manage the transaction for us and SFSB are
the perfect construction for "stateful" data, assigned to one
"client". So the controleur can acces many methods in different
"managers" in the same transaction natively (eg without extra
construction or CODI/@Transaction annotations for example) and this
even if the SFSB does not directly access the DB..
As far as I understood that, you start a transaction on every access to
a public method of your SFSB. Isn't that a bit of an overkill and also
waste? IMO the granularity of the transaction should be finer than that.
If you are using JSF I can't imagine how many "useless transactions" are
started and stopped just for retrieving values from your backing bean.
You could of course define @TransactionAttribute(SUPPORTS) on every
method that should not start a transaction but that's ugly. When you
access your SLSB from within a POJO the transaction is started by the
SLSB, or to be more specific by an interceptor that attached
automatically on your SLSB, if you didn't change the transaction
attribute for the manager.
So mainly if you don't require the transaction to involve a whole method
of your SFSB, and you shouldn't IMO, you don't need SFSBs. It's just
okay to have POJOs. If you really need the transaction over a whole SFSB
method, you probably added logic that should have been in your managers
instead of your backing bean.
Regarding concurrency I can only say that, if you have concerns and
therefore use SFSBs you probably use the wrong scope. Although you might
run into situations where you really need synchronization it is in
general the rare case when you used the right scope.
With EJB 3.1, EJBs are "transparent" (no interfaces, no super class,
no extra constructions), the only difference with a POJO is the
@Stateful annotation and you benefit from the EJB container features)
There are other differences too. For example if you throw a
non-ApplicationException within an EJB, your instance gets destroyed.
From my experiences I can only say that this behavior sucks. Of course
you can annotate a top level exception type with
@ApplicationException(inherited=true) and force yourself to only throw
these kinds of exceptions, but you will probably end up having a lot try
catches...
- "Managers" are only accessed from Controlers
Good.
- some POJOs (Usually conversation scoped to handle data used by
many pages in a conversation)
That's nice too.
- and detached entities directly display in the presentation layer..
so you don't use "open session/entitymanager/connection in view"
right? :D
No
Sean 2 automatically discard the SFSB when the conversation ends
Same for Codi conversation and the default CDI conversation, isn't it?
Yes (I think..lol, learning CDI now, trying to migrate our Seam 2 apps..)
All our apps are architectured like this and this is great ! This
works very well this way our apps are very clear and concise wit the
controler/manager separation. No "dao" no transport layers or "extra
wiring" structures
Maybe a light dao layer or so might be handy in case you want to
abstract away your persistence technology. At least you shouldn't
query the DB directly in the UI Layer IMO.
No need for that for us. KISS..Entities, when detached (after been
"loaded" in a manager) are used like any other POJOs.. (almost)No
difference
If you have these "load methods" in your manager classes it is fine too,
but be aware of the fact that the default behavior of EJB is to invoke
any public method as if it was annotated with
@TransactionAttribute(Required). If you for example put all your "load
methods" into seperate SLSBs you only have to annotate the classes with
@TransactionAttribute(Supports) to avoid starting a transaction every
time such a method gets called. In contrast you would have to annotate
each "load method" with @TransactionAttribute(Supports) to avoid
transactions for these methods.
I would love to see what Gavin King would answer to you on this..lol
About what exactly?
Again I don't follow you in your answer (Usage of ConversationScope
etc..) vs my initial post
You wrote that it worked with the CDI conversation scope but not with
the codi conversation scope.
No I understand
This is another post, Please comment in the other post.
Thx
Cheers
Le 2012-12-12 17:28, Christian Beikov a écrit :
Why do you want to scope something that is stateless? I mean
stateless already is some kind of scope, like pooled application
scoped. Since you don't want to have a state in a stateless bean,
why using a scope that will cause destroying the instance after
conversation end?
You should maybe consider using POJO beans scoped with whatever you
want for your frontend(backing beans for views) and use something
like application scope, singleton or stateless for your beans in
the service layer.
When this is about transaction handling, I can only recommend you
to reconsider defining transactions in a service level but not in
the UI layer. Transactions should also be as short as possible!
Or is it maybe about entity managers being conversation scoped
within the bean instances? In my opinion this is a bad and error
prone practice. Keep your stuff as stateless as possible and use
transaction scope.
If you have no other choice than keeping on using these scopes for
your beans you will probably have to tweak the class loader
configuration as you already mentioned to make it working or
consider using the javax.context.ConversationScoped annotation.
Another option might also be to move the beans into the web
application, but I am not sure if that will work 100% and I also
discourage that.
Mit freundlichen Grüßen,
------------------------------------------------------------------------
*Christian Beikov*
Am 12.12.2012 22:39, schrieb Denis Forveille:
Bad news: In fact, in practice this does not work for us.
We are moving from seam 2/jsf1.2 to cdi/jsf2.0/codi and we use SLSB
(Stateless Session Beans) as JSF backing beans.
Those SLSB may be of scope "ViewScope" (= Seam 2 "PageScope") and
need
to be injected at leats "FacesContext" (to send back messages to the
browser)
So if we want to use the "@ViewAccessScoped" or "@ViewScope" and or
other JSF artefacts (FacesMessages etc.) produced by CODI in our
SLSBs, we need to have the codi-jsf jars visible in the classpath of
the EJB module.
The initial classloader problem with the jsf CODI jars in ear/lib
comes because the JSF lifecycle uses JSF CODI classes loaded by
another classloader than the one used by the WAR
So if we want to setup our application as describes above with CODI,
we have those options left:
- configure the application classloader to "WAR classloader
policy" to
"Application/single" instead of "Module/multiple" and put the CODI
jars in ear/lib and keep PARENT_FIRST for both app and war.
Nothing in
MANIFEST files (Tested OK.)
- configure the application classloader to "WAR classloader
policy" to
"Application/single" instead of "Module/multiple" and put the JSF
CODI
jars at the root of the ear, put the rest of the CODI modules in
ear/lib, keep PARENT_FIRST for both, add manifest entries for the WAR
and EJB modules to the 2 CODI jsf jars (Tested OK)
in brief we need to configure WebSphere to use only one classloader
for the whole modules of the application (ejb+jpa+war+dependent jars)
<truncated>