I have the following entity inheritance, let’s start with the root (it’s just a table with an auto-increment integer ID):
@Entity
@Table(name = "Contacts")
@Inheritance(strategy = InheritanceType.JOINED)
@DiscriminatorColumn(name = "discriminator", discriminatorType = DiscriminatorType.STRING)
public abstract class Contact implements Serializable
{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column
protected Integer id;
...
}
OrganizationalUnit is just a name plus an the inherited ID:
@Entity
@Table(name = "OrganizationalUnits")
public abstract class OrganizationalUnit extends Contact
{
@Column
protected String name;
...
}
Organization is just an empty entity (for being referenced):
@Entity
@Table(name = "Organizations")
public abstract class Organization extends OrganizationalUnit
{
...
}
Last but not least:
@Entity
@Table(name = "Companies")
@DiscriminatorValue(value = "company")
public class Company extends Organization
{
@Basic(optional = false)
@Column(name = "dnd_type")
private String dndType;
...
}
This makes a company have 3 columns/fields: an ID, a name, and a dnd type.
Each company is referenced from a document entity in the system (each document has an owning company):
@Entity
@Table(name = "Documents")
@Inheritance(strategy = InheritanceType.JOINED)
@DiscriminatorColumn(name = "discriminator", discriminatorType = DiscriminatorType.STRING)
public abstract class Document implements Serializable
{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column
protected Integer id;
@Basic(optional = false)
@Column(name = "file_name")
protected String fileName;
@ManyToOne(fetch = FetchType.LAZY, optional = false)
@JoinColumn(name = "company_id", referencedColumnName = "id")
protected Company company;
...
}
Note the @ManyToOne(fetch = FetchType.LAZY, optional = false) on the company relationship. It’s mandatory not to have LAZY here, using EAGER fetch type here FIXES the problem I’m talking about here (but I want to get it to work with LAZY, also because I’m using a code generator to re-generate the entity classes… and it has to work!)
I’m referencing Company‘s dndType for every document in a JSF page pq-edit.xhtml like:
<ui:include src="/subviews/repo-filename-dnd-panel.xhtml">
<ui:param name="document" value="#{doc}" />
<ui:param name="documentFileName" value="#{doc.fileName}" />
<ui:param name="documentCompanyName" value="#{doc.company.name}" />
<ui:param name="documentCompanyDndSuffix" value="#{doc.company.dndType}" /> <!-- EXCEPTION HERE -->
</ui:include>
These are just passed to a subview /subviews/repo-filename-dnd-panel.xhtml, where I just reference the params, e.g. documentCompanyDndSuffix, to construct some HTML.
What I get for #{doc.company.dndType} now is:
13:53:56,043 SEVERE [org.richfaces.log.Context] (http--127.0.0.1-8080-3) /subviews/repo-filename-dnd-panel.xhtml @14,63 type="doc-#{documentCompanyDndSuffix}": /pq-edit.xhtml @139,94 value="#{doc.company.dndType}": org.hibernate.LazyInitializationException: could not initialize proxy - no Session: javax.el.ELException: /subviews/repo-filename-dnd-panel.xhtml @14,63 type="doc-#{documentCompanyDndSuffix}": /pq-edit.xhtml @139,94 value="#{doc.company.dndType}": org.hibernate.LazyInitializationException: could not initialize proxy - no Session
at com.sun.faces.facelets.el.TagValueExpression.getValue(TagValueExpression.java:114) [jsf-impl-2.1.5-jbossorg-1.jar:2.1.5-SNAPSHOT]
at javax.faces.component.ComponentStateHelper.eval(ComponentStateHelper.java:194) [jboss-jsf-api_2.1_spec-2.0.0.Beta1.jar:2.0.0.Beta1]
at javax.faces.component.ComponentStateHelper.eval(ComponentStateHelper.java:182) [jboss-jsf-api_2.1_spec-2.0.0.Beta1.jar:2.0.0.Beta1]
at org.richfaces.component.UIDragSource.getType(UIDragSource.java:95) [richfaces-components-ui-4.1.0.Final.jar:]
at org.richfaces.renderkit.DragSourceRenderer.getOptions(DragSourceRenderer.java:55) [richfaces-components-ui-4.1.0.Final.jar:]
at org.richfaces.renderkit.DnDRenderBase.buildClientScript(DnDRenderBase.java:66) [richfaces-components-ui-4.1.0.Final.jar:]
at org.richfaces.renderkit.DnDRenderBase.buildAndStoreScript(DnDRenderBase.java:43) [richfaces-components-ui-4.1.0.Final.jar:]
at org.richfaces.renderkit.DnDRenderBase.doEncodeEnd(DnDRenderBase.java:74) [richfaces-components-ui-4.1.0.Final.jar:]
at org.richfaces.renderkit.RendererBase.encodeEnd(RendererBase.java:175) [richfaces-components-ui-4.1.0.Final.jar:]
at javax.faces.component.UIComponentBase.encodeEnd(UIComponentBase.java:875) [jboss-jsf-api_2.1_spec-2.0.0.Beta1.jar:2.0.0.Beta1]
at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1763) [jboss-jsf-api_2.1_spec-2.0.0.Beta1.jar:2.0.0.Beta1]
at org.richfaces.renderkit.RendererBase.renderChildren(RendererBase.java:276) [richfaces-components-ui-4.1.0.Final.jar:]
at org.richfaces.renderkit.html.AjaxOutputPanelRenderer.encodeChildren(AjaxOutputPanelRenderer.java:57) [richfaces-components-ui-4.1.0.Final.jar:]
.
. lots of RichFaces and JSF stuff
.
at org.apache.coyote.http11.Http11AprProtocol$Http11ConnectionHandler.process(Http11AprProtocol.java:626) [jbossweb-7.0.7.Final.jar:]
at org.apache.tomcat.util.net.AprEndpoint$Worker.run(AprEndpoint.java:2033) [jbossweb-7.0.7.Final.jar:]
at java.lang.Thread.run(Unknown Source) [:1.7.0_02]
Caused by: org.hibernate.LazyInitializationException: could not initialize proxy - no Session
at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:149) [hibernate-core-4.0.0.Final.jar:4.0.0.Final]
at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:195) [hibernate-core-4.0.0.Final.jar:4.0.0.Final]
at org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer.invoke(JavassistLazyInitializer.java:185) [hibernate-core-4.0.0.Final.jar:4.0.0.Final]
at de.poyry.pqgenerator.model.Company_$$_javassist_22.getDndType(Company_$$_javassist_22.java) [classes:]
at sun.reflect.GeneratedMethodAccessor457.invoke(Unknown Source) [:1.7.0_02]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) [:1.7.0_02]
at java.lang.reflect.Method.invoke(Unknown Source) [:1.7.0_02]
at javax.el.BeanELResolver.getValue(BeanELResolver.java:302) [jboss-el-api_2.2_spec-1.0.0.Final.jar:1.0.0.Final]
at com.sun.faces.el.DemuxCompositeELResolver._getValue(DemuxCompositeELResolver.java:176) [jsf-impl-2.1.5-jbossorg-1.jar:2.1.5-SNAPSHOT]
at com.sun.faces.el.DemuxCompositeELResolver.getValue(DemuxCompositeELResolver.java:203) [jsf-impl-2.1.5-jbossorg-1.jar:2.1.5-SNAPSHOT]
at org.apache.el.parser.AstValue.getValue(AstValue.java:169) [jbossweb-7.0.7.Final.jar:]
at org.apache.el.ValueExpressionImpl.getValue(ValueExpressionImpl.java:189) [jbossweb-7.0.7.Final.jar:]
at org.jboss.weld.el.WeldValueExpression.getValue(WeldValueExpression.java:50) [weld-core-1.1.4.Final.jar:2011-11-22 20:01]
at com.sun.faces.facelets.el.TagValueExpression.getValue(TagValueExpression.java:109) [jsf-impl-2.1.5-jbossorg-1.jar:2.1.5-SNAPSHOT]
at org.apache.el.parser.AstIdentifier.getValue(AstIdentifier.java:67) [jbossweb-7.0.7.Final.jar:]
at org.apache.el.parser.AstDeferredExpression.getValue(AstDeferredExpression.java:44) [jbossweb-7.0.7.Final.jar:]
at org.apache.el.parser.AstCompositeExpression.getValue(AstCompositeExpression.java:50) [jbossweb-7.0.7.Final.jar:]
at org.apache.el.ValueExpressionImpl.getValue(ValueExpressionImpl.java:189) [jbossweb-7.0.7.Final.jar:]
at org.jboss.weld.el.WeldValueExpression.getValue(WeldValueExpression.java:50) [weld-core-1.1.4.Final.jar:2011-11-22 20:01]
at com.sun.faces.facelets.el.TagValueExpression.getValue(TagValueExpression.java:109) [jsf-impl-2.1.5-jbossorg-1.jar:2.1.5-SNAPSHOT]
... 72 more
I have no clue why I get a LazyInitializationException here, given that the Company entity doesn’t hint LAZY to Hibernate 4 and the previous call to #{doc.company.name} works fine.
Update:
I’ve recently tested this on GlassFish 3.1.2 and all is fine. So I’m beginning to believe it’s some kind of JBoss AS 7 or rather JBoss AS transaction management issue/policy mismatch.
My assumption is that the company name was accessed and unproxied during some transaction and after the entity manager was closed the dndType is accessed which hasn’t been unproxied yet (whereas the name has been)… it looks to me like an EJB transaction handling problem (where I really still have a deficit)…
I’ll add more info here soon.
The problem was that the company wasn’t fetched in the statement – that simple. I just had the occasional luck in similar situations that a transaction was still active, so this one appeared to be failing, but in fact the others did, too.
I failed to realize that when accessed from a JSF page, the method which got the list of documents from the DB has already run and the transaction was already gone.