Hi,
Thanks for the updates.
I solved the problem using the following strategy:
I defined two interfaces, one called ItemController and the other
called TagsController. Each of these interfaces implements
GenericController which is defined as being @Remote. Each each of the
subinterfaces I put in the methods that are specific for that type
(i.e., getItemByIdAndItemName in ItemController and
getItemByIdAndTagOrderNumber in TagsController).
Then I made the GenericControllerBean abstract and removed the
@Stateless annotation.
In each of the ItemControllerBean and TagsControllerBean concrete
classes, I made them extend GenericController and implement their
interface and annotate as being @Stateless, i.e.,
@Stateless
public class ItemControllerBean extends GenericControllerBean<Item>
implements ItemController
Now it works. I can have one class called GenericControllerBean that
does generic stuff like persisting and merging, removing and find'ing
by id. Then in each of the subclasses I can get them to do specific
type work....
Wonderful.
Thanks Cheng for your helpful comments. It made me think :-)
-=david=-
On 3/30/07, Cheng Fang <Cheng.Fang_at_sun.com> wrote:
>
>
> David Harrigan wrote:
> > Hi,
> >
> > Firstly, I really do apologise for the length of this email, but it's the
> > only way I can explain what is going on to support my question. I've hit
> > a real problem in trying to get something which I thought would work, to
> > actually work.
> >
> > I've pasted the code below, but my question is this:
> >
> > It appears that I can't have a sub-subclass of a @Remote Interface. In
> > the example
> > below ItemControllerBean and TagsControllerBean reference the same
> > @Remote interface. If I try to deploy this, Glassfish blows up saying
> > it can't rebind the EJB. If I
> > remove one of the @Remote's (say from TagsControllerBean) it all works
> > fine.
> >
> Multiple EJBs should be able to have the same business interfaces. Do
> you have sun-ejb-jar.xml to specify a <jndi-name> for each bean? This
> may help avoid conflict.
> > This is a problem since I'm trying to use generics to simplify my
> > code. You see,
> > the GenericControllerBean only knows how to CRUD types - this is
> > common across all of my entities. The specialisation comes into the
> > subtype (i.e., ItemControllerBean) since it knows how to do some
> > specific work that only relates to Items.
> >
> > So, what am I missing here? Is what I am attempting not allowed
> > according to the EJB specification? Or perhaps it is allowed, but GF
> > should be able to be clever in knowing that I'm referencing the same
> > Remote interface.
> >
> > On another note, but relevant, why can't it be the case that if I
> > remove @Remote from both ItemControllerBean and TagsControllerBean
> > that the system should know that because these two objects inherit -
> > indirectly - from GenericController, that GenericController should be
> > treated as the @Remote interface - instead of me explicitly setting
> > @Remote on these two classes? Is that not allowed according to EJB
> > spec?
> Not supported in EJB 3.0. For this to work, your bean classes need to
> have the intended business interface in its implements clause.
>
> -cheng
> >
> > I thank you for taking the time to look at this. I do hope you can help.
> >
> > -=david=-
> >
> > Here's the class hierarchy (I've removed some code (exceptions,
> > logging)):
> >
> > @Remote
> > public interface GenericController<T> {
> >
> > void insert(T type) throws DatabaseException;
> > void remove(T type) throws DatabaseException;
> > T update(T type) throws DatabaseException;
> > T getById(int typeId) throws DatabaseException;
> > String getEntityName();
> > EntityManager getEntityManager();
> > }
> >
> > public class GenericControllerBean<T> implements GenericController<T> {
> >
> > private final Class<T> entityClass;
> > private final String entityClassName;
> >
> > @PersistenceContext(unitName = "mediaPu")
> > private EntityManager em;
> >
> > @SuppressWarnings("unchecked")
> > public GenericControllerBean() {
> > this.entityClass =
> > (Class<T>)((ParameterizedType)getClass().getGenericSuperclass()).getActualTypeArguments()[0];
> >
> > entityClassName = entityClass.getSimpleName();
> > }
> >
> > @SuppressWarnings("unchecked")
> > public GenericControllerBean(final EntityManager em) {
> > this();
> > this.em = em;
> > }
> >
> > @Override
> > public String getEntityName() {
> > return entityClassName;
> > }
> >
> > @Override
> > public EntityManager getEntityManager() {
> > return em;
> > }
> >
> > @Override
> > public T getById(final int typeId) {
> > return em.find(entityClass, typeId);
> > }
> >
> > @Override
> > public void insert(final T type) {
> > em.persist(type);
> > }
> >
> > @Override
> > public void remove(final T type) throws DatabaseException {
> > em.remove(type);
> > }
> >
> > @Override
> > public T update(final T type) throws DatabaseException {
> > em.merge(type);
> > }
> > }
> >
> > @Stateless
> > @Remote(GenericController.class)
> > public class ItemControllerBean extends GenericControllerBean<Item> {
> > public ItemControllerBean() {
> > }
> >
> > public ItemControllerBean(final EntityManager em) {
> > super(em);
> > }
> >
> > public Item getItemById(final int itemId) throws DatabaseException {
> > return getEntityManager().find(Item.class, itemId);
> > }
> > }
> >
> > @Stateless
> > @Remote(GenericController.class)
> > public class TagsControllerBean extends GenericControllerBean<Tags> {
> >
> > public TagsControllerBean() {
> >
> > }
> >
> > public TagsControllerBean(final EntityManager em) {
> > super(em);
> > }
> >
> > }
> >
> > In a WebService, I have this
> >
> > @EJB
> > ItemControllerBean itemController
> >
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: ejb-unsubscribe_at_glassfish.dev.java.net
> For additional commands, e-mail: ejb-help_at_glassfish.dev.java.net
>
>
--
PGP Key Id: E2BE72FC
Public Key: http://www.harrigan.info/public.asc