如何在Vaadin 7中注入EJB以在CustomComponent中使用?

时间:2013-07-29 11:24:19

标签: java jpa ejb-3.0 vaadin code-injection

我使用以下内容:

  • Eclipse Java EE Juno
  • GlassFish 3.1.2,
  • DerbyDB,
  • JPA,
  • EclipseLink和
  • Vaadin 7.1.1。

此外,我是Glassfish,DerbyDB,JPA,EcliseLink和Vaadin的新手:-) 如果我错了,请纠正我!


首先: 请注意,有几个examples using the Application class,但由于这是关于Vaadin 6,它不适合我。

我希望使用JPA在Derby DB中保留实体Member,但我现在已经困难了两天了。我尝试做的是注入一个无状态EJB MemberManagerBean,它有一个EntityManager来管理实体Member,在Vaadin UI的任何地方使用它CustomComponent创建布局。

package de.ves.beans.entities;

import java.io.Serializable;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Version;

@Entity
public class Member implements Serializable {

    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    protected Long id;

    @Version
    @Column(name = "OPTLOCK")
    private Long version;

    protected String name;

    public Member(){}

    // getters and setters ...

}

package de.ves.beans.mgm;

import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

import de.ves.beans.entities.Member;

@Stateless
public class MemberManagerBean implements MemberManagerLocal {

    @PersistenceContext
    protected EntityManager entityManager;

    @Override
    public Member getMember(Long id) {
        return entityManager.find(Member.class, id);
    }

    @Override
    public Member saveMember(Member member) {
        if (member.getId() == null){
            entityManager.persist(member);
        }else{
            entityManager.merge(member);
        }
        return member;
    }

}

package de.ves.beans.mgm;

import javax.ejb.Local;
import javax.ejb.TransactionAttribute;

import de.ves.beans.entities.Member;

@TransactionAttribute
@Local
public interface MemberManagerLocal {

    public Member getMember(Long id);

    public Member saveMember(Member member);

}

package de.ves.ui;

import javax.servlet.annotation.WebServlet;

import com.vaadin.annotations.Theme;
import com.vaadin.annotations.Title;
import com.vaadin.annotations.VaadinServletConfiguration;
import com.vaadin.navigator.Navigator;
import com.vaadin.server.VaadinRequest;
import com.vaadin.server.VaadinServlet;
import com.vaadin.ui.UI;

import de.ves.beans.mgm.MemberManagerBean;
import de.ves.club.Friends;
import de.ves.club.Members;
import de.ves.club.News;
import de.ves.contact.About;
import de.ves.home.Home;
import de.ves.media.Pics;
import de.ves.media.Videos;

@SuppressWarnings("serial")
@Theme("ves")
public class VesUI extends UI {

    private Navigator navigator;

    @WebServlet(value = "/*", asyncSupported = true)
    @VaadinServletConfiguration(productionMode = false, ui = VesUI.class)
    public static class Servlet extends VaadinServlet {

    }

    @Override
    protected void init(VaadinRequest request) {
        navigator = new Navigator(this, this);

        // Home

        MainLayout main = new MainLayout();
        main.setMiddle(new Home());
        navigator.addView(Home.PATH, main); 

        // ErrorView

        navigator.setErrorView(main);

        // Subpages

        main = new MainLayout();
        main.setMiddle(new Members());
        navigator.addView(Members.PATH, main);

                    // ...

    }

}

package de.ves.club;

import com.vaadin.addon.jpacontainer.JPAContainer;
import com.vaadin.addon.jpacontainer.JPAContainerFactory;
import com.vaadin.annotations.AutoGenerated;
import com.vaadin.server.FileResource;
import com.vaadin.shared.ui.label.ContentMode;
import com.vaadin.ui.Alignment;
import com.vaadin.ui.CustomComponent;
import com.vaadin.ui.Label;
import com.vaadin.ui.Panel;
import com.vaadin.ui.VerticalLayout;

import de.ves.beans.entities.Member;

@SuppressWarnings("serial")
public class Members extends CustomComponent {


            // Components and stuff...


    public Members() {
        buildMainLayout();
        setCompositionRoot(mainLayout);

        pnl_root.setSizeFull();

        // Several inits...

                    // This is where I want to read/write from/into the DB.
                    // This is not possible since I can't access the 
                    // MemberManagerBean. The following code shows my approach
                    // concering with a JPAContainer.

        JPAContainer<Member> members = JPAContainerFactory.make(Member.class, "vesPersistence");
        Member m = new Member();
        members.addEntity(m);

    }

    @AutoGenerated
    private VerticalLayout buildMainLayout() {
        // ...
    }

            // ...

}

<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="
      http://java.sun.com/xml/ns/persistence
      http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
    version="2.0">
    <persistence-unit name="vesPersistence">
        <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
        <class>de.ves.beans.entities.Member</class>
        <exclude-unlisted-classes>false</exclude-unlisted-classes>
        <properties>
            <property name="eclipselink.target-database" value="Derby" />
            <property name="javax.persistence.jdbc.driver" value="org.apache.derby.jdbc.ClientDriver" />
            <property name="javax.persistence.jdbc.url" value="jdbc:derby://localhost:1527/ves;create=true" />
            <property name="javax.persistence.jdbc.user" value="admin" />
            <property name="javax.persistence.jdbc.password" value="..." />
            <property name="eclipselink.ddl-generation" value="drop-and-create-tables" />
            <property name="eclipselink.logging.level" value="INFO" />
        </properties>
    </persistence-unit>
</persistence>

我的第一种方法是在CustomComponent ...

中注入EJB
    @EJB
    private MemberManagerBean memberManager;

...但这导致NullPointerException

我读到注射仅适用于Servlet。 (这是对的吗?)


现在,问题在于,与普通DWP不同,在Vaadin项目中(在MY Vaadin项目中)只有一个Servlet,这是UI中的静态类。应用程序内部的导航通过Navigator进行,其他Servlets是不必要的。虽然注入静态Servlet对我来说是错误的,但我尝试了这种方法。再次,NullPointerException


第三种方法:按照on vaadin.com使用JPAContainer。这几乎正​​常,但触发ServletException。请参阅Members类中的代码。

它触发了以下内容:

javax.servlet.ServletException:com.vaadin.server.ServiceException:java.lang.IllegalStateException: 异常描述:使用JTA时无法使用EntityTransaction。

我无法解释为什么会这样。


我的最后一种方法是关注this forum thread,但也导致了NullPointerException。此外,我真的不想使用它,因为它似乎是一种解决方法。


我很想使用JPAContainer,但在Vaadin中使用JPA的常用方法确实会有所帮助。

就是这样。能帮到我吗:-)在此先感谢您的帮助!

0 个答案:

没有答案