Hello,
We have built our production application using EJB 3.0 on JBoss Application
server 4.0.3 SP1. Here is the description of the problem we are encountering:
The problem is really that JBoss can not load EJB 3.0 entity beans which map to
more than one table in the database.
Here is the real life scenario that describes the problem.
? The application schema contains an object called Application and it
maps to it's own table in the database:
create Table Application
{
int applicationId; (Primary key)
varchar name;
varchar description;
}
? 2. Then we have another security object called VirtualRight and it's
table structure is:
create Table VirtualRight
{
int virtualRightId; (Primary key)
varchar name;
varchar description;
int applicationId; (Foreign key)
}
There is one-to-many association between the application and virtual right
objects.
With EJB 3.0 the relationship between these 2 objects are defined in the
following way:
Application.java
@Entity()
public class Application
{
private int applicationId;
private String name;
private String description;
private VirtualRight[] virtualRights;
@Id (generate = GeneratorType.AUTO)
@Column (name = "applicationId")
public int getApplicationId() {
return applicationId;
}
@Column (name = "name")
public String getName() {
return name;
}
@Column (name = "description")
public String getDescription() {
return description;
}
@OneToMany (cascade = CascadeType.ALL, fetch = FetchType.LAZY,
mappedBy = "application")
@IndexColumn(name = "appl_vright_index")
public VirtualRight[] getVirtualRights() {
return virtualRights;
}
}
VirtualRight.java
@Entity()
public class VirtualRight
{
private int virtualRightId;
private String name;
private String description;
private Application application;
@Id (generate = GeneratorType.AUTO)
@Column (name = "virtualRightId")
public int getVirtualRightId() {
return virtualRightId;
}
@Column (name = "name")
public String getName() {
return name;
}
@Column (name = "description")
public String getDescription() {
return description;
}
@ManyToOne
@JoinColumn (name = "applicationId")
public Application getApplication() {
return application;
}
}
As can be seen from code, the Application object since has one-to-many
relationship with VirtualRight, has to declare the member ?virtualRights? as an
array or collection as per the EJB 3.0 specifications.
Also since the VirtualRight object has many-to-one relationship with
Application, it has to declare member ?application?.
EJB 3.0 defines an interface called EntityManager as part of the Persistence
API, that should be used from a session bean to load and store the 3.0 entity
beans from the persistence store.
So here Is the sample code that loads an Application object based on name:
@PersistenceContext (type=PersistenceContextType.TRANSACTION)
private EntityManager manager;
public Application findApplicationByName(String appName)
{
Query query = manager.createQuery("from Application a where a.name = :name");
Application appl = (Application)query.setParameter("name",
appName).getSingleResult();
Return (appl);
}
The method ?findApplicationByName? uses the createQuery method defined by the
EntityManager interface to fetch an Application object from the database. As
can be seen from the code above the query is supposed to load the
?virtualRights? member of the Application object if found and this is where the
problem exists in the JBoss application server.
The query.getSingleResult() call fails with the exception message:
org.hibernate.HibernateException: null index column for collection:
com.eds.autoeng.vcc.security.ejb.Application.virtualRights
In reality the Application object can exist without any corresponding
VirtualRight objects and consequently the ?virtualRights? member would be null.
Ironically the query fails as soon as you insert one VirtualRight in the
database for an Application object. So to be more precise:
? The Application object is loaded successfully when it has no associated
VirtualRights populated.
? The query to load the Application object fails with the above
mentioned exception soon after a VirtualRight is inserted in the database
associated with the Application.
This behavior is really weird and points to some bug in the EJB 3.0
implementation of JBoss application server, unless there is something wrong in
the way the relations have been defined.
We have tested this application on the latest EJB 3.0 RC4 and it fails with the
same reason.
An obvious workaround to this problem in the query implementation is to use
named queries or native queries to load the Entity bean instances. Here is the
code that loads the Application object using the NamedQuery feature from the
EJB query language.
@Entity()
@NamedQuery (
name="findApplicationWithName",
queryString="SELECT applicationId, description FROM Application a where
a.name = :name"
)
public class Application implements java.io.Serializable
{
?.. Application class details
}
Here is the Session bean that uses the NamedQuery to load the Application
object.
public @Stateless class ApplicationsBean implements Applications
{
@PersistenceContext (type=PersistenceContextType.TRANSACTION)
private EntityManager manager;
public Application queryApplicationByName(String appName)
{
Object appIdAndDescr[] =
(Object[])manager.createNamedQuery("findApplicationWithName")
.setParameter("name", appName).getSingleResult();
Application appl = null;
if (appIdAndDescr != null)
{
appl = new Application();
appl.setName(appName);
appl.setApplicationId(((Integer)appIdAndDescr[0]).intValue());
appl.setDescription((String)appIdAndDescr[1]);
}
return appl;
}
}
Please note that the above query does not load the Virtual rights associated
with the Application object and so that brings us to the next hurdle - When you
try to persist the 'Application' fetched after adding one or more
VirtualRights, the merge operation fails.
We are running against time to solve this problem as the release date has
already slipped.
Any help on resolving this issue will be greately appreciated.
Thanks,
Milind
View the original post :
http://www.jboss.com/index.html?module=bb&op=viewtopic&p=3921064#3921064
Reply to the post :
http://www.jboss.com/index.html?module=bb&op=posting&mode=reply&p=3921064
-------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc. Do you grep through log files
for problems? Stop! Download the new AJAX search engine that makes
searching your log files as easy as surfing the web. DOWNLOAD SPLUNK!
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=103432&bid=230486&dat=121642
_______________________________________________
JBoss-user mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/jboss-user