You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@tapestry.apache.org by Adam Zimowski <zi...@gmail.com> on 2010/11/04 22:55:00 UTC

EJB3 Statefull Session Beans and Tapestry IOC - possible?

Hi Experts -

Our business (service) layers lives within OpenEJB on a remote host.
Most of our business logic (DAOs, etc) are stateless session beans. We
were able to elegantly define them as Tapestry services using standard
static module builder. Here is our (simplified) EjbModule with one
statless EJB:

/**
 * Defines all aspect of EJB remoting. Each EJB becomes a singleton
 * Tapestry IOC service, and can be used from a page or component
 * via @Inject or @InjectService.
 *
 * @author Adam Zimowski
 */
public class EjbModule {

	private static final Logger log =
LoggerFactory.getLogger(EcommerceModule.class);

	public static Context buildEjbContext(@Inject @Value("${ejb.host}")
String aEjbHost) {
		
		if(log.isDebugEnabled()) log.debug("EJB host: " + aEjbHost);
		
		Properties p = new Properties();
		p.put(Context.INITIAL_CONTEXT_FACTORY,
"org.apache.openejb.client.RemoteInitialContextFactory");
		p.put(Context.PROVIDER_URL, aEjbHost);
		
		Context ctx = null;
		
		try {
			ctx = new InitialContext(p);
		}
		catch(NamingException ne) {
			log.error("EJB host lookup error!", ne);
		}

		return ctx;
	}
	
	public static CatalogServiceRemote
buildCatalogService(@InjectService("EjbContext") Context aEjbContext)
{
		
		CatalogServiceRemote catalogService = null;
		
		try {
			Object ref = aEjbContext.lookup("CatalogServiceEjbRemote");
			catalogService =
				(CatalogServiceRemote)PortableRemoteObject.narrow(ref,
CatalogServiceRemote.class);
		}
		catch(NamingException ne) {
			log.error("Unable to create " +
CatalogServiceRemote.class.getSimpleName(), ne);
		}
		
		return catalogService;
	}
}

Works perfectly. In a page or component we simply do:

@InjectService("CatalogService")
private CatalogServiceRemote catalogService;

and we're talking to a statless EJB on a remote host.

Things become a bit tricky with a statfull session bean. I don't see
how I can use the same approach since I now need to retain a state
meaning I need to hold onto a specific EJB instance per request.

What's the preferred and recommended way to use statefull session
beans within a Tapestry application?

The closest I've got was to define some sort of a factory, and store
the proxy in the HttpSession. May work, but so ugly comparing to our
elegant solution with statless beans.

Any ideas highly appreciated.

Adam

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
For additional commands, e-mail: users-help@tapestry.apache.org


Re: EJB3 Statefull Session Beans and Tapestry IOC - possible?

Posted by Adam Zimowski <zi...@gmail.com>.
Of course in the 2nd paragraph I meant to say:

"I think it's best NOT to open this FOR discussion too deeply"

:-)

On Mon, Nov 8, 2010 at 2:25 PM, Adam Zimowski <zi...@gmail.com> wrote:
> So I figured out somewhat decent stateful ejb (3) integration into
> Tapestry. Here is what we did, in the interest to complete this thread
> and provide some level of documentation for future.
>
> First, regarding the architecture, I think it's best to open this
> discussion too deeply. This kind of stuff can easily side track the
> discussion. For the purpose of this entire thread consider the fact
> that we have multiple front ends to the same business logic (EJBs).
> Tapestry (web), SOAP (web services) and Eclipse RPC (fat client). Our
> model dictates that HttpSession is used ONLY to retain state pertinent
> to the UI (page flow, element configuration etc). All business state
> is managed by the EJBs and consequently stored within SFSBs. We do not
> want to re-engineer business state mechanism for each UI.
>
> Having said that, back to Tapestry..
>
> Since DI is not an option with SFSBs given only two available
> lifecycles Tapestry comes with out of the box
> (PerThreadServiceLifecycle and SingletonServiceLifecycle), without
> implementing a custom lifecycle (PerHttpSessionServiceLifecycle) Tap
> IOC will never know how to retain SFSB proxy within the HttpSession.
>
> However, a very much DI-like mechanism can be accomplished with
> @SessionState. In the nutshell, in any page or component we now do:
>
> @SessionState
> private MyStatefulEjbRemote statefulEjb;
>
> And Tapestry either creates stateful bean instance, or pulls it out of
> the session if one already exists. Of course, for this to work we need
> an ApplicationStateContribution and the actual ApplicationStateManager
> configuration. Thanks to generics, this can be a minimal burden:
>
> public class EjbModule {
>
>        /**
>         * Builds ApplicationStateContribution (ASC) with the underlying
> ApplicationStateCreator able to
>         * produce a stateful EJB, based on the arguments provided.
>         *
>         * @param <T> The stateful EJB type
>         * @param aEjbContext a valid jndi context used to look up the ejb
>         * @param aEjbJndiName
>         * @param aEjbInterface
>         * @return
>         */
>        private <T> ApplicationStateContribution buildEjbAsc(final Context
> aEjbContext, final String aEjbJndiName, final Class<?> aEjbInterface)
> {
>
>                ApplicationStateCreator<T> creator = new ApplicationStateCreator<T>() {
>                        @SuppressWarnings("unchecked")
>                        public T create() {
>                                T service = null;
>                                try {
>                                        Object ref = aEjbContext.lookup(aEjbJndiName);
>                                        service =
>                                                (T)PortableRemoteObject.narrow(ref, aEjbInterface);
>                                }
>                                catch(NamingException ne) {
>                                        log.error("Unable to create " + aEjbInterface.getSimpleName(), ne);
>                                }
>
>                                return service;
>                        }
>                };
>
>                return new ApplicationStateContribution("session", creator);
>        }
>
>        /**
>         * Tell Tapestry which stateful EJBs are to be used with @SessionState.
>         *
>         * @param configuration
>         * @param aEjbContext
>         */
>        public void contributeApplicationStateManager(
>                        MappedConfiguration<Class<?>,
>                        ApplicationStateContribution> configuration,
>                        final @InjectService("EjbContext") Context aEjbContext) {
>
>                configuration.add(StatefulMessageRemote.class,
> buildEjbAsc(aEjbContext, "StatefulMessageEjbRemote",
> StatefulMessageRemote.class));
>                configuration.add(StatefulNumberRemote.class,
> buildEjbAsc(aEjbContext, "StatefulNumberEjbRemote",
> StatefulNumberRemote.class));
>                configuration.add(CounterRemote.class, buildEjbAsc(aEjbContext,
> "CounterEjbRemote", CounterRemote.class));
>        }
>
> }
>
> As you can see, the generics-enabled buildEjbAsc reduces individual
> SFSB contributions down to one line of code.
>
> That's really all you need to get somewhat decent integration of EJB3
> stateful session beans with your Tapestry applications. Now.... the
> ugly side.. Of course, there are some obvious issues, main one being
> session timeout (on both ends: servlet container vs. ejb container)
> and synchronization of such. We found that it's possible to write (on
> OpenEJB) a custom passivator that works in-tandem with HttpSession but
> that's too much work, and we are lazy around here :-)
>
> The scheme we use is to set SFSB timeout much larger (but finite) than
> HttpSession timeout. For example, if Jetty's session times out in two
> hours, our stateful bean container times out SFSBs after 12 hours of
> inactivity. (Don't worry about our other UI clients and what effects
> this may have on them).  While not perfect, this should never break.
> For this to be exploited we'd have to have an active HttpSession
> longer than 12 hours while not invoking SFSB call during entire time -
> very unlikely.
>
> With that said, we still need to clean up the ejbs, particularly when
> HttpSession itself is timed out. HttpSessionListener does a nice trick
> here:
>
> public class StatefulEjbDestroyer implements HttpSessionListener {
>
>        private static final Logger log =
> LoggerFactory.getLogger(StatefulEjbDestroyer.class);
>
>        @Override
>        public void sessionCreated(HttpSessionEvent aEvent) {
>                HttpSession session = aEvent.getSession();
>                log.debug("--> session created [" + session.getId() + "]");
>        }
>
>        @SuppressWarnings("unchecked")
>        @Override
>        public void sessionDestroyed(HttpSessionEvent aEvent) {
>                HttpSession session = aEvent.getSession();
>                log.debug("--> destroying stateful EJBs from session [" +
> session.getId() + "]");
>                Enumeration<String> attributeNames = session.getAttributeNames();
>                while(attributeNames.hasMoreElements()) {
>                        String name = attributeNames.nextElement();
>                        Object attribute = session.getAttribute(name);
>                        if(attribute instanceof DestroyableEjb) {
>                                DestroyableEjb ejb = (DestroyableEjb)attribute;
>                                log.debug("sending destroy signal for " + ejb.getEjbInfo());
>                                ejb.destroy();
>                        }
>                }
>        }
>
> }
>
> The DestroyableEjb is part of our scheme. Under our model any SFSB
> remote interface extends DestroyableEjb. This way we know which
> HttpSession object is the SFSB. We found that due to Tapestry's
> internal session management, same cleanup mechanism cannot be
> implemented with HttpSessionAttributeListener as Tapestry swaps
> session attributes in between requests retaining them elsewhere (its
> internal structures). I think this is due the 5.2 performance
> enhancement, but not sure. In any case, attempting to clean up the EJB
> in attributeRemoved will not do the trick, so keep that in mind.
>
> That's about it. I know there are better solutions to this problem,
> but having searched the mailing list I didn't find a single one so at
> least something is documented. The idea of creating
> PerHttpSessionServiceLifecycle so that stateful beans could
> potentially be injected with @InjectService is somewhat intriguing to
> me, but honestly, a bit over my head given my limited experience with
> Tapestry (5).
>
> Kind Regards,
> Adam
>
> On Fri, Nov 5, 2010 at 10:06 AM, Christian Riedel
> <cr...@googlemail.com> wrote:
>> Hi Adam,
>>
>> perthread-services are recreated on each request...
>>
>>> PERTHREAD
>>> An alternate scope provided with Tapestry; a per-thread instance is created on demand, behind a shared proxy.
>>
>> You could create a simple Object to hold your proxy instead and store it in the session. Something like that:
>>
>>> @SessionState private SFSBWrappingObject yourService;
>>
>> http://tapestry.apache.org/tapestry5.1/guide/appstate.html
>> http://tapestry.apache.org/tapestry5.1/apidocs/org/apache/tapestry5/annotations/SessionState.html
>> http://tapestry.apache.org/tapestry5.1/apidocs/org/apache/tapestry5/services/ApplicationStateManager.html
>>
>> If it's an option to have your Tapestry-App and the OpenEJB backend merged you could try out Tapestry Jumpstart's approach of integrating OpenEJB with Tapestry:
>>
>> http://jumpstart.doublenegative.com.au/
>>
>> It's quite unfortunate architecture to have stateful services on a remote machine... aren't there any alternatives speaking of architecture?
>>
>> Best,
>> Christian
>>
>>
>> Am 05.11.2010 um 12:56 schrieb Adam Zimowski:
>>
>>> Hi Christian -
>>>
>>> I did not know about @Scope annotation and it is nice. To answer your
>>> question yes, we need to retain a specific sfsb proxy instance per
>>> session, so yes, across multiple requests. Can I annotate service
>>> builder method with @Scope to tell Tap IOC to pull a specific instance
>>> for a session? Or is it purely a global singleton override to merely
>>> return a new instance for each @Inject ?
>>>
>>> To put it differently I would expect Tap IOC to be aware of user
>>> sessions, store sfsb for each session in some sort of a map and on
>>> each @Inject/@InjectService look up the map, if there pull the
>>> instance otherwise create new one.
>>>
>>> Adam
>>>
>>> On Fri, Nov 5, 2010 at 5:51 AM, Thiago H. de Paula Figueiredo
>>> <th...@gmail.com> wrote:
>>>> On Fri, 05 Nov 2010 08:30:52 -0200, adasal <ad...@gmail.com> wrote:
>>>>
>>>>> Hi Christian,
>>>>
>>>> Hi, guys!
>>>>
>>>>> You know Tapestry very well.
>>>>> Do you have any points of comparison with JEE JSF, e.g. Ice  Faces?
>>>>> It seems to me that JSF is very similar (by borrowed design) to Tapestry.
>>>>> But there must be technical points of significant difference?
>>>>
>>>> I know very little about JSF, but Tapestry 5 is very, very different from
>>>> JSF. The similarity is that their built on Java and are component
>>>> (event)-oriented frameworks.
>>>>
>>>> * Tapestry 5 doesn't use XML configuration besides web.xml, JSF does.
>>>> * JSF has a very complicated lifecycle, Tapestry doesn't.
>>>> * Tapestry is built and configured on an IoC framework, JSF doesn't, so you
>>>> can adapt it to your needs way simpler than JSF.
>>>> * Writing components in Tapestry is way easier.
>>>> * Tapestry has live class reloading, JSF doesn't.
>>>> * In Tapestry, pages are objects in a very OOP sense, while JSF, IMHO,
>>>> doesn't have a page concept. In Tapestry, there's a 1:1:1 relationship
>>>> between the page class, its template and its URL.
>>>> * Tapestry has its own template engine, not using JSP. JSF uses JSP (which
>>>> sucks) or Facelets (which its own documentation says that it was inspired
>>>> from Tapestry's template engine).
>>>> * Tapestry doesn't store page rendering information anywhere, JSF does.
>>>> * Tapestry 5 has native AJAX support. As far as I know, JSF doesn't have.
>>>> * JSF is an specification with two implementations which aren't 100%
>>>> compatible with each other. Tapestry is a framework.
>>>>
>>>> I could go on and on . . .
>>>>
>>>> --
>>>> Thiago H. de Paula Figueiredo
>>>> Independent Java, Apache Tapestry 5 and Hibernate consultant, developer, and
>>>> instructor
>>>> Owner, Ars Machina Tecnologia da Informação Ltda.
>>>> http://www.arsmachina.com.br
>>>>
>>>> ---------------------------------------------------------------------
>>>> To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
>>>> For additional commands, e-mail: users-help@tapestry.apache.org
>>>>
>>>>
>>>
>>> ---------------------------------------------------------------------
>>> To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
>>> For additional commands, e-mail: users-help@tapestry.apache.org
>>>
>>
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
>> For additional commands, e-mail: users-help@tapestry.apache.org
>>
>>
>

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
For additional commands, e-mail: users-help@tapestry.apache.org


Re: EJB3 Statefull Session Beans and Tapestry IOC - possible?

Posted by Adam Zimowski <zi...@gmail.com>.
So I figured out somewhat decent stateful ejb (3) integration into
Tapestry. Here is what we did, in the interest to complete this thread
and provide some level of documentation for future.

First, regarding the architecture, I think it's best to open this
discussion too deeply. This kind of stuff can easily side track the
discussion. For the purpose of this entire thread consider the fact
that we have multiple front ends to the same business logic (EJBs).
Tapestry (web), SOAP (web services) and Eclipse RPC (fat client). Our
model dictates that HttpSession is used ONLY to retain state pertinent
to the UI (page flow, element configuration etc). All business state
is managed by the EJBs and consequently stored within SFSBs. We do not
want to re-engineer business state mechanism for each UI.

Having said that, back to Tapestry..

Since DI is not an option with SFSBs given only two available
lifecycles Tapestry comes with out of the box
(PerThreadServiceLifecycle and SingletonServiceLifecycle), without
implementing a custom lifecycle (PerHttpSessionServiceLifecycle) Tap
IOC will never know how to retain SFSB proxy within the HttpSession.

However, a very much DI-like mechanism can be accomplished with
@SessionState. In the nutshell, in any page or component we now do:

@SessionState
private MyStatefulEjbRemote statefulEjb;

And Tapestry either creates stateful bean instance, or pulls it out of
the session if one already exists. Of course, for this to work we need
an ApplicationStateContribution and the actual ApplicationStateManager
configuration. Thanks to generics, this can be a minimal burden:

public class EjbModule {

	/**
	 * Builds ApplicationStateContribution (ASC) with the underlying
ApplicationStateCreator able to
	 * produce a stateful EJB, based on the arguments provided.
	 *
	 * @param <T> The stateful EJB type
	 * @param aEjbContext a valid jndi context used to look up the ejb
	 * @param aEjbJndiName
	 * @param aEjbInterface
	 * @return
	 */
	private <T> ApplicationStateContribution buildEjbAsc(final Context
aEjbContext, final String aEjbJndiName, final Class<?> aEjbInterface)
{

		ApplicationStateCreator<T> creator = new ApplicationStateCreator<T>() {
			@SuppressWarnings("unchecked")
			public T create() {
				T service = null;
				try {
					Object ref = aEjbContext.lookup(aEjbJndiName);
					service =
						(T)PortableRemoteObject.narrow(ref, aEjbInterface);
				}
				catch(NamingException ne) {
					log.error("Unable to create " + aEjbInterface.getSimpleName(), ne);
				}

				return service;
			}
		};

		return new ApplicationStateContribution("session", creator);
	}

	/**
	 * Tell Tapestry which stateful EJBs are to be used with @SessionState.
	 *
	 * @param configuration
	 * @param aEjbContext
	 */
	public void contributeApplicationStateManager(
			MappedConfiguration<Class<?>,
			ApplicationStateContribution> configuration,
			final @InjectService("EjbContext") Context aEjbContext) {

		configuration.add(StatefulMessageRemote.class,
buildEjbAsc(aEjbContext, "StatefulMessageEjbRemote",
StatefulMessageRemote.class));
		configuration.add(StatefulNumberRemote.class,
buildEjbAsc(aEjbContext, "StatefulNumberEjbRemote",
StatefulNumberRemote.class));
		configuration.add(CounterRemote.class, buildEjbAsc(aEjbContext,
"CounterEjbRemote", CounterRemote.class));
	}

}

As you can see, the generics-enabled buildEjbAsc reduces individual
SFSB contributions down to one line of code.

That's really all you need to get somewhat decent integration of EJB3
stateful session beans with your Tapestry applications. Now.... the
ugly side.. Of course, there are some obvious issues, main one being
session timeout (on both ends: servlet container vs. ejb container)
and synchronization of such. We found that it's possible to write (on
OpenEJB) a custom passivator that works in-tandem with HttpSession but
that's too much work, and we are lazy around here :-)

The scheme we use is to set SFSB timeout much larger (but finite) than
HttpSession timeout. For example, if Jetty's session times out in two
hours, our stateful bean container times out SFSBs after 12 hours of
inactivity. (Don't worry about our other UI clients and what effects
this may have on them).  While not perfect, this should never break.
For this to be exploited we'd have to have an active HttpSession
longer than 12 hours while not invoking SFSB call during entire time -
very unlikely.

With that said, we still need to clean up the ejbs, particularly when
HttpSession itself is timed out. HttpSessionListener does a nice trick
here:

public class StatefulEjbDestroyer implements HttpSessionListener {

	private static final Logger log =
LoggerFactory.getLogger(StatefulEjbDestroyer.class);
	
	@Override
	public void sessionCreated(HttpSessionEvent aEvent) {
		HttpSession session = aEvent.getSession();
		log.debug("--> session created [" + session.getId() + "]");
	}

	@SuppressWarnings("unchecked")
	@Override
	public void sessionDestroyed(HttpSessionEvent aEvent) {
		HttpSession session = aEvent.getSession();
		log.debug("--> destroying stateful EJBs from session [" +
session.getId() + "]");
		Enumeration<String> attributeNames = session.getAttributeNames();
		while(attributeNames.hasMoreElements()) {
			String name = attributeNames.nextElement();
			Object attribute = session.getAttribute(name);
			if(attribute instanceof DestroyableEjb) {
				DestroyableEjb ejb = (DestroyableEjb)attribute;
				log.debug("sending destroy signal for " + ejb.getEjbInfo());
				ejb.destroy();
			}
		}
	}

}

The DestroyableEjb is part of our scheme. Under our model any SFSB
remote interface extends DestroyableEjb. This way we know which
HttpSession object is the SFSB. We found that due to Tapestry's
internal session management, same cleanup mechanism cannot be
implemented with HttpSessionAttributeListener as Tapestry swaps
session attributes in between requests retaining them elsewhere (its
internal structures). I think this is due the 5.2 performance
enhancement, but not sure. In any case, attempting to clean up the EJB
in attributeRemoved will not do the trick, so keep that in mind.

That's about it. I know there are better solutions to this problem,
but having searched the mailing list I didn't find a single one so at
least something is documented. The idea of creating
PerHttpSessionServiceLifecycle so that stateful beans could
potentially be injected with @InjectService is somewhat intriguing to
me, but honestly, a bit over my head given my limited experience with
Tapestry (5).

Kind Regards,
Adam

On Fri, Nov 5, 2010 at 10:06 AM, Christian Riedel
<cr...@googlemail.com> wrote:
> Hi Adam,
>
> perthread-services are recreated on each request...
>
>> PERTHREAD
>> An alternate scope provided with Tapestry; a per-thread instance is created on demand, behind a shared proxy.
>
> You could create a simple Object to hold your proxy instead and store it in the session. Something like that:
>
>> @SessionState private SFSBWrappingObject yourService;
>
> http://tapestry.apache.org/tapestry5.1/guide/appstate.html
> http://tapestry.apache.org/tapestry5.1/apidocs/org/apache/tapestry5/annotations/SessionState.html
> http://tapestry.apache.org/tapestry5.1/apidocs/org/apache/tapestry5/services/ApplicationStateManager.html
>
> If it's an option to have your Tapestry-App and the OpenEJB backend merged you could try out Tapestry Jumpstart's approach of integrating OpenEJB with Tapestry:
>
> http://jumpstart.doublenegative.com.au/
>
> It's quite unfortunate architecture to have stateful services on a remote machine... aren't there any alternatives speaking of architecture?
>
> Best,
> Christian
>
>
> Am 05.11.2010 um 12:56 schrieb Adam Zimowski:
>
>> Hi Christian -
>>
>> I did not know about @Scope annotation and it is nice. To answer your
>> question yes, we need to retain a specific sfsb proxy instance per
>> session, so yes, across multiple requests. Can I annotate service
>> builder method with @Scope to tell Tap IOC to pull a specific instance
>> for a session? Or is it purely a global singleton override to merely
>> return a new instance for each @Inject ?
>>
>> To put it differently I would expect Tap IOC to be aware of user
>> sessions, store sfsb for each session in some sort of a map and on
>> each @Inject/@InjectService look up the map, if there pull the
>> instance otherwise create new one.
>>
>> Adam
>>
>> On Fri, Nov 5, 2010 at 5:51 AM, Thiago H. de Paula Figueiredo
>> <th...@gmail.com> wrote:
>>> On Fri, 05 Nov 2010 08:30:52 -0200, adasal <ad...@gmail.com> wrote:
>>>
>>>> Hi Christian,
>>>
>>> Hi, guys!
>>>
>>>> You know Tapestry very well.
>>>> Do you have any points of comparison with JEE JSF, e.g. Ice  Faces?
>>>> It seems to me that JSF is very similar (by borrowed design) to Tapestry.
>>>> But there must be technical points of significant difference?
>>>
>>> I know very little about JSF, but Tapestry 5 is very, very different from
>>> JSF. The similarity is that their built on Java and are component
>>> (event)-oriented frameworks.
>>>
>>> * Tapestry 5 doesn't use XML configuration besides web.xml, JSF does.
>>> * JSF has a very complicated lifecycle, Tapestry doesn't.
>>> * Tapestry is built and configured on an IoC framework, JSF doesn't, so you
>>> can adapt it to your needs way simpler than JSF.
>>> * Writing components in Tapestry is way easier.
>>> * Tapestry has live class reloading, JSF doesn't.
>>> * In Tapestry, pages are objects in a very OOP sense, while JSF, IMHO,
>>> doesn't have a page concept. In Tapestry, there's a 1:1:1 relationship
>>> between the page class, its template and its URL.
>>> * Tapestry has its own template engine, not using JSP. JSF uses JSP (which
>>> sucks) or Facelets (which its own documentation says that it was inspired
>>> from Tapestry's template engine).
>>> * Tapestry doesn't store page rendering information anywhere, JSF does.
>>> * Tapestry 5 has native AJAX support. As far as I know, JSF doesn't have.
>>> * JSF is an specification with two implementations which aren't 100%
>>> compatible with each other. Tapestry is a framework.
>>>
>>> I could go on and on . . .
>>>
>>> --
>>> Thiago H. de Paula Figueiredo
>>> Independent Java, Apache Tapestry 5 and Hibernate consultant, developer, and
>>> instructor
>>> Owner, Ars Machina Tecnologia da Informação Ltda.
>>> http://www.arsmachina.com.br
>>>
>>> ---------------------------------------------------------------------
>>> To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
>>> For additional commands, e-mail: users-help@tapestry.apache.org
>>>
>>>
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
>> For additional commands, e-mail: users-help@tapestry.apache.org
>>
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
> For additional commands, e-mail: users-help@tapestry.apache.org
>
>

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
For additional commands, e-mail: users-help@tapestry.apache.org


Re: EJB3 Statefull Session Beans and Tapestry IOC - possible?

Posted by Christian Riedel <cr...@googlemail.com>.
Hi Adam,

perthread-services are recreated on each request...

> PERTHREAD 
> An alternate scope provided with Tapestry; a per-thread instance is created on demand, behind a shared proxy.

You could create a simple Object to hold your proxy instead and store it in the session. Something like that:

> @SessionState private SFSBWrappingObject yourService; 

http://tapestry.apache.org/tapestry5.1/guide/appstate.html
http://tapestry.apache.org/tapestry5.1/apidocs/org/apache/tapestry5/annotations/SessionState.html
http://tapestry.apache.org/tapestry5.1/apidocs/org/apache/tapestry5/services/ApplicationStateManager.html

If it's an option to have your Tapestry-App and the OpenEJB backend merged you could try out Tapestry Jumpstart's approach of integrating OpenEJB with Tapestry:

http://jumpstart.doublenegative.com.au/

It's quite unfortunate architecture to have stateful services on a remote machine... aren't there any alternatives speaking of architecture?

Best,
Christian


Am 05.11.2010 um 12:56 schrieb Adam Zimowski:

> Hi Christian -
> 
> I did not know about @Scope annotation and it is nice. To answer your
> question yes, we need to retain a specific sfsb proxy instance per
> session, so yes, across multiple requests. Can I annotate service
> builder method with @Scope to tell Tap IOC to pull a specific instance
> for a session? Or is it purely a global singleton override to merely
> return a new instance for each @Inject ?
> 
> To put it differently I would expect Tap IOC to be aware of user
> sessions, store sfsb for each session in some sort of a map and on
> each @Inject/@InjectService look up the map, if there pull the
> instance otherwise create new one.
> 
> Adam
> 
> On Fri, Nov 5, 2010 at 5:51 AM, Thiago H. de Paula Figueiredo
> <th...@gmail.com> wrote:
>> On Fri, 05 Nov 2010 08:30:52 -0200, adasal <ad...@gmail.com> wrote:
>> 
>>> Hi Christian,
>> 
>> Hi, guys!
>> 
>>> You know Tapestry very well.
>>> Do you have any points of comparison with JEE JSF, e.g. Ice  Faces?
>>> It seems to me that JSF is very similar (by borrowed design) to Tapestry.
>>> But there must be technical points of significant difference?
>> 
>> I know very little about JSF, but Tapestry 5 is very, very different from
>> JSF. The similarity is that their built on Java and are component
>> (event)-oriented frameworks.
>> 
>> * Tapestry 5 doesn't use XML configuration besides web.xml, JSF does.
>> * JSF has a very complicated lifecycle, Tapestry doesn't.
>> * Tapestry is built and configured on an IoC framework, JSF doesn't, so you
>> can adapt it to your needs way simpler than JSF.
>> * Writing components in Tapestry is way easier.
>> * Tapestry has live class reloading, JSF doesn't.
>> * In Tapestry, pages are objects in a very OOP sense, while JSF, IMHO,
>> doesn't have a page concept. In Tapestry, there's a 1:1:1 relationship
>> between the page class, its template and its URL.
>> * Tapestry has its own template engine, not using JSP. JSF uses JSP (which
>> sucks) or Facelets (which its own documentation says that it was inspired
>> from Tapestry's template engine).
>> * Tapestry doesn't store page rendering information anywhere, JSF does.
>> * Tapestry 5 has native AJAX support. As far as I know, JSF doesn't have.
>> * JSF is an specification with two implementations which aren't 100%
>> compatible with each other. Tapestry is a framework.
>> 
>> I could go on and on . . .
>> 
>> --
>> Thiago H. de Paula Figueiredo
>> Independent Java, Apache Tapestry 5 and Hibernate consultant, developer, and
>> instructor
>> Owner, Ars Machina Tecnologia da Informação Ltda.
>> http://www.arsmachina.com.br
>> 
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
>> For additional commands, e-mail: users-help@tapestry.apache.org
>> 
>> 
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
> For additional commands, e-mail: users-help@tapestry.apache.org
> 


---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
For additional commands, e-mail: users-help@tapestry.apache.org


Re: EJB3 Statefull Session Beans and Tapestry IOC - possible?

Posted by Adam Zimowski <zi...@gmail.com>.
Hi Christian -

I did not know about @Scope annotation and it is nice. To answer your
question yes, we need to retain a specific sfsb proxy instance per
session, so yes, across multiple requests. Can I annotate service
builder method with @Scope to tell Tap IOC to pull a specific instance
for a session? Or is it purely a global singleton override to merely
return a new instance for each @Inject ?

To put it differently I would expect Tap IOC to be aware of user
sessions, store sfsb for each session in some sort of a map and on
each @Inject/@InjectService look up the map, if there pull the
instance otherwise create new one.

Adam

On Fri, Nov 5, 2010 at 5:51 AM, Thiago H. de Paula Figueiredo
<th...@gmail.com> wrote:
> On Fri, 05 Nov 2010 08:30:52 -0200, adasal <ad...@gmail.com> wrote:
>
>> Hi Christian,
>
> Hi, guys!
>
>> You know Tapestry very well.
>> Do you have any points of comparison with JEE JSF, e.g. Ice  Faces?
>> It seems to me that JSF is very similar (by borrowed design) to Tapestry.
>> But there must be technical points of significant difference?
>
> I know very little about JSF, but Tapestry 5 is very, very different from
> JSF. The similarity is that their built on Java and are component
> (event)-oriented frameworks.
>
> * Tapestry 5 doesn't use XML configuration besides web.xml, JSF does.
> * JSF has a very complicated lifecycle, Tapestry doesn't.
> * Tapestry is built and configured on an IoC framework, JSF doesn't, so you
> can adapt it to your needs way simpler than JSF.
> * Writing components in Tapestry is way easier.
> * Tapestry has live class reloading, JSF doesn't.
> * In Tapestry, pages are objects in a very OOP sense, while JSF, IMHO,
> doesn't have a page concept. In Tapestry, there's a 1:1:1 relationship
> between the page class, its template and its URL.
> * Tapestry has its own template engine, not using JSP. JSF uses JSP (which
> sucks) or Facelets (which its own documentation says that it was inspired
> from Tapestry's template engine).
> * Tapestry doesn't store page rendering information anywhere, JSF does.
> * Tapestry 5 has native AJAX support. As far as I know, JSF doesn't have.
> * JSF is an specification with two implementations which aren't 100%
> compatible with each other. Tapestry is a framework.
>
> I could go on and on . . .
>
> --
> Thiago H. de Paula Figueiredo
> Independent Java, Apache Tapestry 5 and Hibernate consultant, developer, and
> instructor
> Owner, Ars Machina Tecnologia da Informação Ltda.
> http://www.arsmachina.com.br
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
> For additional commands, e-mail: users-help@tapestry.apache.org
>
>

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
For additional commands, e-mail: users-help@tapestry.apache.org


Re: EJB3 Statefull Session Beans and Tapestry IOC - possible?

Posted by "Thiago H. de Paula Figueiredo" <th...@gmail.com>.
On Fri, 05 Nov 2010 08:30:52 -0200, adasal <ad...@gmail.com> wrote:

> Hi Christian,

Hi, guys!

> You know Tapestry very well.
> Do you have any points of comparison with JEE JSF, e.g. Ice  Faces?
> It seems to me that JSF is very similar (by borrowed design) to Tapestry.
> But there must be technical points of significant difference?

I know very little about JSF, but Tapestry 5 is very, very different from  
JSF. The similarity is that their built on Java and are component  
(event)-oriented frameworks.

* Tapestry 5 doesn't use XML configuration besides web.xml, JSF does.
* JSF has a very complicated lifecycle, Tapestry doesn't.
* Tapestry is built and configured on an IoC framework, JSF doesn't, so  
you can adapt it to your needs way simpler than JSF.
* Writing components in Tapestry is way easier.
* Tapestry has live class reloading, JSF doesn't.
* In Tapestry, pages are objects in a very OOP sense, while JSF, IMHO,  
doesn't have a page concept. In Tapestry, there's a 1:1:1 relationship  
between the page class, its template and its URL.
* Tapestry has its own template engine, not using JSP. JSF uses JSP (which  
sucks) or Facelets (which its own documentation says that it was inspired  
 from Tapestry's template engine).
* Tapestry doesn't store page rendering information anywhere, JSF does.
* Tapestry 5 has native AJAX support. As far as I know, JSF doesn't have.
* JSF is an specification with two implementations which aren't 100%  
compatible with each other. Tapestry is a framework.

I could go on and on . . .

-- 
Thiago H. de Paula Figueiredo
Independent Java, Apache Tapestry 5 and Hibernate consultant, developer,  
and instructor
Owner, Ars Machina Tecnologia da Informação Ltda.
http://www.arsmachina.com.br

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
For additional commands, e-mail: users-help@tapestry.apache.org


Re: EJB3 Statefull Session Beans and Tapestry IOC - possible?

Posted by adasal <ad...@gmail.com>.
Hi Christian,
You know Tapestry very well.
Do you have any points of comparison with JEE JSF, e.g. Ice  Faces?

It seems to me that JSF is very similar (by borrowed design) to Tapestry.
But there must be technical points of significant difference?
I haven't dived down to find these.

I'm working for a company called Yell Labs, which is trying in some way to
turn around a book based (paper published) directory service and align it
with the internet.
Of course it does have an on line presence and the whole thing is an
interesting, if a bit depressing and long, business story that collides with
a story of technical difficulty and ineptness.

Unfortunately, I'm afraid we are still being inept.

Best,

Adam

On 4 November 2010 23:11, Christian Riedel <cr...@googlemail.com> wrote:

> Hi Adam,
>
> do you need to use the sfsb across multiple requests as a kind of
> conversational bean or is it sufficient to hold the reference for the time
> of one request?
> You can define a Tapestry-Service's scope as "per-thread" (1) so you could
> wrap the connection to your remote inside a service similar to your current
> approach.
> For proper conversational support in T5 you could also utilize Tynamo's
> module (2). That way you would avoid storing proxys directly in the session.
>
> The right solution depends on your use case :)
>
> (1)
> http://tapestry.apache.org/tapestry5.1/apidocs/org/apache/tapestry5/ioc/annotations/Scope.html
> (2) http://tynamo.org/tapestry-conversations+guide
>
> Best
> Christian
>
>
> Am 04.11.2010 um 22:55 schrieb Adam Zimowski:
>
> > Hi Experts -
> >
> > Our business (service) layers lives within OpenEJB on a remote host.
> > Most of our business logic (DAOs, etc) are stateless session beans. We
> > were able to elegantly define them as Tapestry services using standard
> > static module builder. Here is our (simplified) EjbModule with one
> > statless EJB:
> >
> > /**
> > * Defines all aspect of EJB remoting. Each EJB becomes a singleton
> > * Tapestry IOC service, and can be used from a page or component
> > * via @Inject or @InjectService.
> > *
> > * @author Adam Zimowski
> > */
> > public class EjbModule {
> >
> >       private static final Logger log =
> > LoggerFactory.getLogger(EcommerceModule.class);
> >
> >       public static Context buildEjbContext(@Inject @Value("${ejb.host}")
> > String aEjbHost) {
> >
> >               if(log.isDebugEnabled()) log.debug("EJB host: " +
> aEjbHost);
> >
> >               Properties p = new Properties();
> >               p.put(Context.INITIAL_CONTEXT_FACTORY,
> > "org.apache.openejb.client.RemoteInitialContextFactory");
> >               p.put(Context.PROVIDER_URL, aEjbHost);
> >
> >               Context ctx = null;
> >
> >               try {
> >                       ctx = new InitialContext(p);
> >               }
> >               catch(NamingException ne) {
> >                       log.error("EJB host lookup error!", ne);
> >               }
> >
> >               return ctx;
> >       }
> >
> >       public static CatalogServiceRemote
> > buildCatalogService(@InjectService("EjbContext") Context aEjbContext)
> > {
> >
> >               CatalogServiceRemote catalogService = null;
> >
> >               try {
> >                       Object ref =
> aEjbContext.lookup("CatalogServiceEjbRemote");
> >                       catalogService =
> >
> (CatalogServiceRemote)PortableRemoteObject.narrow(ref,
> > CatalogServiceRemote.class);
> >               }
> >               catch(NamingException ne) {
> >                       log.error("Unable to create " +
> > CatalogServiceRemote.class.getSimpleName(), ne);
> >               }
> >
> >               return catalogService;
> >       }
> > }
> >
> > Works perfectly. In a page or component we simply do:
> >
> > @InjectService("CatalogService")
> > private CatalogServiceRemote catalogService;
> >
> > and we're talking to a statless EJB on a remote host.
> >
> > Things become a bit tricky with a statfull session bean. I don't see
> > how I can use the same approach since I now need to retain a state
> > meaning I need to hold onto a specific EJB instance per request.
> >
> > What's the preferred and recommended way to use statefull session
> > beans within a Tapestry application?
> >
> > The closest I've got was to define some sort of a factory, and store
> > the proxy in the HttpSession. May work, but so ugly comparing to our
> > elegant solution with statless beans.
> >
> > Any ideas highly appreciated.
> >
> > Adam
> >
> > ---------------------------------------------------------------------
> > To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
> > For additional commands, e-mail: users-help@tapestry.apache.org
> >
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
> For additional commands, e-mail: users-help@tapestry.apache.org
>
>

Re: EJB3 Statefull Session Beans and Tapestry IOC - possible?

Posted by Christian Riedel <cr...@googlemail.com>.
Hi Adam,

do you need to use the sfsb across multiple requests as a kind of conversational bean or is it sufficient to hold the reference for the time of one request?
You can define a Tapestry-Service's scope as "per-thread" (1) so you could wrap the connection to your remote inside a service similar to your current approach. 
For proper conversational support in T5 you could also utilize Tynamo's module (2). That way you would avoid storing proxys directly in the session. 

The right solution depends on your use case :) 

(1) http://tapestry.apache.org/tapestry5.1/apidocs/org/apache/tapestry5/ioc/annotations/Scope.html
(2) http://tynamo.org/tapestry-conversations+guide

Best
Christian


Am 04.11.2010 um 22:55 schrieb Adam Zimowski:

> Hi Experts -
> 
> Our business (service) layers lives within OpenEJB on a remote host.
> Most of our business logic (DAOs, etc) are stateless session beans. We
> were able to elegantly define them as Tapestry services using standard
> static module builder. Here is our (simplified) EjbModule with one
> statless EJB:
> 
> /**
> * Defines all aspect of EJB remoting. Each EJB becomes a singleton
> * Tapestry IOC service, and can be used from a page or component
> * via @Inject or @InjectService.
> *
> * @author Adam Zimowski
> */
> public class EjbModule {
> 
> 	private static final Logger log =
> LoggerFactory.getLogger(EcommerceModule.class);
> 
> 	public static Context buildEjbContext(@Inject @Value("${ejb.host}")
> String aEjbHost) {
> 		
> 		if(log.isDebugEnabled()) log.debug("EJB host: " + aEjbHost);
> 		
> 		Properties p = new Properties();
> 		p.put(Context.INITIAL_CONTEXT_FACTORY,
> "org.apache.openejb.client.RemoteInitialContextFactory");
> 		p.put(Context.PROVIDER_URL, aEjbHost);
> 		
> 		Context ctx = null;
> 		
> 		try {
> 			ctx = new InitialContext(p);
> 		}
> 		catch(NamingException ne) {
> 			log.error("EJB host lookup error!", ne);
> 		}
> 
> 		return ctx;
> 	}
> 	
> 	public static CatalogServiceRemote
> buildCatalogService(@InjectService("EjbContext") Context aEjbContext)
> {
> 		
> 		CatalogServiceRemote catalogService = null;
> 		
> 		try {
> 			Object ref = aEjbContext.lookup("CatalogServiceEjbRemote");
> 			catalogService =
> 				(CatalogServiceRemote)PortableRemoteObject.narrow(ref,
> CatalogServiceRemote.class);
> 		}
> 		catch(NamingException ne) {
> 			log.error("Unable to create " +
> CatalogServiceRemote.class.getSimpleName(), ne);
> 		}
> 		
> 		return catalogService;
> 	}
> }
> 
> Works perfectly. In a page or component we simply do:
> 
> @InjectService("CatalogService")
> private CatalogServiceRemote catalogService;
> 
> and we're talking to a statless EJB on a remote host.
> 
> Things become a bit tricky with a statfull session bean. I don't see
> how I can use the same approach since I now need to retain a state
> meaning I need to hold onto a specific EJB instance per request.
> 
> What's the preferred and recommended way to use statefull session
> beans within a Tapestry application?
> 
> The closest I've got was to define some sort of a factory, and store
> the proxy in the HttpSession. May work, but so ugly comparing to our
> elegant solution with statless beans.
> 
> Any ideas highly appreciated.
> 
> Adam
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
> For additional commands, e-mail: users-help@tapestry.apache.org
> 


---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
For additional commands, e-mail: users-help@tapestry.apache.org