-
1. Re: How do I make an EntityHome subclass stateful?
ericjava.eric.chiralsoftware.net Aug 1, 2008 4:43 AM (in response to keithbannister)Don't.
Create a long-running conversation and make sure that your EntityHome thing is part of it. Seam keeps a conversation-scoped cache, so that's what you want.
------------
-
2. Re: How do I make an EntityHome subclass stateful?
keithbannister Aug 1, 2008 8:27 AM (in response to keithbannister)OK that's fine, but according the tutorial http://docs.jboss.com/seam/2.0.1.GA/reference/en/html/tutorial.html#d0e1568 (hotel booking example) I have to make my bean Stateful, when I do that I get
org.jboss.seam.InstantiationException: Could not instantiate Seam component: radioSourceHome at org.jboss.seam.Component.newInstance(Component.java:1962) at org.jboss.seam.Component.getInstance(Component.java:1865) at org.jboss.seam.Component.getInstance(Component.java:1832) at org.jboss.seam.Namespace.getComponentInstance(Namespace.java:55) at org.jboss.seam.Namespace.getComponentInstance(Namespace.java:50) at org.jboss.seam.el.SeamELResolver.resolveBase(SeamELResolver.java:166) at org.jboss.seam.el.SeamELResolver.getValue(SeamELResolver.java:53) at javax.el.CompositeELResolver.getValue(CompositeELResolver.java:53) at com.sun.faces.el.FacesCompositeELResolver.getValue(FacesCompositeELResolver.java:64) at org.jboss.seam.core.Validators$ValidatingResolver.getValue(Validators.java:182) at org.jboss.el.parser.AstIdentifier.getValue(AstIdentifier.java:44) at org.jboss.el.parser.AstValue.getTarget(AstValue.java:34) at org.jboss.el.parser.AstValue.setValue(AstValue.java:83) at org.jboss.el.ValueExpressionImpl.setValue(ValueExpressionImpl.java:249) at org.jboss.seam.core.Validators.validate(Validators.java:140) at org.jboss.seam.navigation.Param.validateConvertedValue(Param.java:237) at org.jboss.seam.navigation.Pages.convertAndValidateStringValuesInPageContext(Pages.java:743) at org.jboss.seam.navigation.Pages.postRestore(Pages.java:393) at org.jboss.seam.jsf.SeamPhaseListener.postRestorePage(SeamPhaseListener.java:528) at org.jboss.seam.jsf.SeamPhaseListener.afterRestoreView(SeamPhaseListener.java:374) at org.jboss.seam.jsf.SeamPhaseListener.afterServletPhase(SeamPhaseListener.java:211) at org.jboss.seam.jsf.SeamPhaseListener.afterPhase(SeamPhaseListener.java:184) at com.sun.faces.lifecycle.LifecycleImpl.phase(LifecycleImpl.java:280) at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:117) at javax.faces.webapp.FacesServlet.service(FacesServlet.java:244) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:83) at org.jboss.seam.debug.hot.HotDeployFilter.doFilter(HotDeployFilter.java:68) at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69) at org.jboss.seam.web.MultipartFilter.doFilter(MultipartFilter.java:85) at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69) at org.jboss.seam.web.ExceptionFilter.doFilter(ExceptionFilter.java:64) at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69) at org.jboss.seam.web.RedirectFilter.doFilter(RedirectFilter.java:44) at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69) at org.ajax4jsf.webapp.BaseXMLFilter.doXmlFilter(BaseXMLFilter.java:141) at org.ajax4jsf.webapp.BaseFilter.doFilter(BaseFilter.java:281) at org.jboss.seam.web.Ajax4jsfFilter.doFilter(Ajax4jsfFilter.java:60) at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69) at org.jboss.seam.web.LoggingFilter.doFilter(LoggingFilter.java:58) at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69) at org.jboss.seam.servlet.SeamFilter.doFilter(SeamFilter.java:158) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) at org.jboss.web.tomcat.filters.ReplyHeaderFilter.doFilter(ReplyHeaderFilter.java:96) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:230) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175) at org.jboss.web.tomcat.security.SecurityAssociationValve.invoke(SecurityAssociationValve.java:179) at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:432) at org.jboss.web.tomcat.security.JaccContextValve.invoke(JaccContextValve.java:84) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127) at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102) at org.jboss.web.tomcat.service.jca.CachedConnectionValve.invoke(CachedConnectionValve.java:157) at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:262) at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:844) at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:583) at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:446) at java.lang.Thread.run(Thread.java:595) Caused by: javax.naming.NameNotFoundException: RadioSourceHome not bound at org.jnp.server.NamingServer.getBinding(NamingServer.java:529) at org.jnp.server.NamingServer.getBinding(NamingServer.java:537) at org.jnp.server.NamingServer.getObject(NamingServer.java:543) at org.jnp.server.NamingServer.lookup(NamingServer.java:267) at sun.reflect.GeneratedMethodAccessor99.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:585) at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:294) at sun.rmi.transport.Transport$1.run(Transport.java:153) at java.security.AccessController.doPrivileged(Native Method) at sun.rmi.transport.Transport.serviceCall(Transport.java:149) at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:466) at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:707) at java.lang.Thread.run(Thread.java:595) at sun.rmi.transport.StreamRemoteCall.exceptionReceivedFromServer(StreamRemoteCall.java:247) at sun.rmi.transport.StreamRemoteCall.executeCall(StreamRemoteCall.java:223) at sun.rmi.server.UnicastRef.invoke(UnicastRef.java:126) at org.jnp.server.NamingServer_Stub.lookup(Unknown Source) at org.jnp.interfaces.NamingContext.lookup(NamingContext.java:667) at org.jnp.interfaces.NamingContext.lookup(NamingContext.java:627) at javax.naming.InitialContext.lookup(InitialContext.java:351) at org.jboss.seam.Component.instantiateSessionBean(Component.java:1279) at org.jboss.seam.Component.instantiate(Component.java:1265) at org.jboss.seam.Component.newInstance(Component.java:1958) ... 61 more
-
3. Re: How do I make an EntityHome subclass stateful?
keithbannister Aug 1, 2008 8:43 AM (in response to keithbannister)Perhaps I should describe my problem better.
I have a page I can navigate to using a url like this:
http://localhost:8080/most/RadioSource.seam?radioSourceId=2403
This page has a number of graphs on it, each of which references the same (large) list of data that I only want to retrieve from the database once.
To plot a graph, I use the following XHTML:
<s:graphicImage value="#{radioSourceHome.decChart}" />
and I have a corresponding function in RadioSourceHome:
@Factory(value="decChart") public byte[] getDecChart() { List<Measurements> meas = getMeasurements(); return createDecChart(meas); }
So my problem is, in the original version, getMeasurements() would go to the database each time.
But I want to cache the results of getMeasurements() so I don't have go to the database each time.
Here's what I have
@Name("radioSourceHome") // @Stateful - uncommenting this breaks - see above post public class RadioSourceHome extends EntityHome<RadioSource> { @In @Out List<Measurements> measurements; ... @Factory public List<Measurements> getMeasurements() { if (measurements == null) { measurements = em.createQuery()..... } return measurements; } @Factory(value="decChart") public byte[] getDecChart() { List<Measurements> meas = getMeasurements(); return createDecChart(meas); }
My question is: Is this the right way to do it? if not, how?
EntityHome manages to get a magical copy of the parent object I'm interested in by parsing the URL, so I'd like to leverage that if possible (I don't know how it's getting this magical copy, I just know I can get it by calling getInstance()).
Help appreciated.
-
4. Re: How do I make an EntityHome subclass stateful?
obfuscator Aug 1, 2008 11:10 AM (in response to keithbannister)I can only guess that you get some sort of naming problem using generics in your interface. Check your jndiView (JndiView.list method) in Jboss jmx console when your app is running, there you will have all your beans with jndi names listed. Perhaps you get some sort of deployment error?
-
5. Re: How do I make an EntityHome subclass stateful?
stefanotravelli Aug 1, 2008 2:46 PM (in response to keithbannister)What you really want is to put 'measurement' in a PAGE or CONVERSATION scope.
In order to achieve this you don't need to extends EntityHome. Either annotate the component with @Scope(ScopeType.CONVERSATION) or specify that scope type in @Out or (better) @Factory annotations.
That is:
@Factory(value="decChart", scope = ScopeType.CONVERSATION) public byte[] getDecChart() { List<Measurements> meas = getMeasurements(); return createDecChart(meas); }
Btw. Components that extends EntityHome are indeed statefull, even if they are not statefull session bean. Go ahead in the Seam documentation: chapter 3 will clarify you about the contextual component model.
Hope this helps.
stefano -
6. Re: How do I make an EntityHome subclass stateful?
stefanotravelli Aug 1, 2008 3:33 PM (in response to keithbannister)Maybe my previous response is a little cryptic.
Here is the long story:
Create a Home componente for the entity:
@Name("radioSourceHome') public RadioSourceHome extends EntityHome<RadioSource> { public void setRadioSourceId(Long id) { setId(id); } public Long getRadioSourceId() { return (Long) getId(); } .... }
Create a component with a factory for the data:
@Name("chartController") public ChartController extends PersistenceController { @In(create = true) RadioSourceHome radioSourceHome; @Factory(value = "chartData", scope = ScopeType.CONVERSATION) public byte[] getChartData() { RadioSource radioSource = radioSourceHome.getInstance(); return createDecChart(getEntityManager().createQuery()....); } ... }
In the chart.xhtml template you'll have:
<s:graphicImage value="#{charData}" />
And this is the chart.page.xml:
<begin-conversation join="true" /> <param name="radioSourceId" value="#{radioSourceHome.radioSourceId}" /> ...
The first line says: when entering this page begin a conversation context or join an existing one.
The second says: take
radioSourceId
parameter and put it in the property evaluated by this expression. The expression asks for a radioSourceHome component, so, if it's not already there, a RadioSourceHome will be created and stored in the conversation context. Then the parameter value is set so that the magic in EntityHome will retrieve your entity.In the xhtml template, the graphicImage tag value attribute looks for
chartData
. The first time the page is displayed Seam won't find this variabile, but during startup it was registered thatchartData
has a factory method in thechartController
component.
So the ChartController component is instantiated, RadioSourceHome get injected and the getChartData method invoked.The result will be placed in the conversation context (you can opt for a PAGE context here, depending on your needs), so that in subsequent calls inside the same conversation the cached value will be used instead of calling the method.
Regards
stefano