繁体   English   中英

无状态EJB在企业应用程序客户端中引发NullPointerException

[英]Stateless EJB throwing NullPointerException in Enterprise Application Client

我对Java EE相对较新,并且对于如何从企业应用程序客户端访问无状态Java Bean感到有些困惑。

我的意图是让我的企业bean CarReposityImpl处理称为Car的实体类的数据库访问和实体管理。

我的CarRepositoryImpl看起来像:

@Stateless
public class CarRepositoryImpl implements CarRepository
{   
    @PersistenceContext(unitName = "FIT5042AssignmentEJBPU")
    private EntityManager entityManager;

    @Override
    public void addCar(Car car)
    {
        entityManager.persist(car);
    }

    @Override
    public Car searchByVIN(String vin) throws Exception
    {
        Car car = entityManager.find(Car.class, vin);
        return car;
    }

    @Override
    public List<Car> getAllCars() throws Exception 
    {        
        return entityManager.createNamedQuery(Car.GET_ALL_QUERY_NAME).getResultList();
    }

    @Override
    public void removeCar(String vin) throws Exception 
    {          
        Car car = searchByVIN(vin);

        if (car != null) 
        {
            entityManager.remove(car);
        }
    }    

    @Override
    public void editCar(Car car) throws Exception 
    {      
        entityManager.merge(car);
    }    
}

它实现的接口CarRepository如下所示:

@Remote
public interface CarRepository 
{
    public void addCar(Car car);
    public Car searchByVIN(String vin) throws Exception;
    public List<Car> getAllCars() throws Exception;
    public void removeCar(String vin) throws Exception;
    public void editCar(Car car) throws Exception;
}

实体类Car看起来像:

@Entity
@Table(name = "CAR")
@NamedQueries({@NamedQuery(name = Car.GET_ALL_QUERY_NAME, query = "SELECT c FROM Car AS c")})
public class Car implements Serializable
{
    public static final String GET_ALL_QUERY_NAME = "Car.getAll";
    //private Sale sale;
    String modelNo, VIN, model, make, type, thumbnail, description, prevURL;

    public Car() {
    }

    public Car(String varModelNo, String varVIN, String varModel, String varMake, String varType, String varThumb, String varDesc, String varPrevURL)
    {
        modelNo = varModelNo;
        VIN = varVIN;
        model = varModel;
        make = varMake;
        type = varType;
        thumbnail = varThumb;
        description = varDesc;
        prevURL = varPrevURL;
    }

    public void setModelNo(String varModNo){modelNo = varModNo;}
    public void setVIN(String varVIN){VIN = varVIN;}
    public void setModel(String varMod){model = varMod;}
    public void setMake(String varMake){make = varMake;}
    public void setType(String varType){type = varType;}
    public void setThumbnail(String varThumb){thumbnail = varThumb;}
    public void setDesc(String varDesc){description = varDesc;}
    public void setPrevURL(String varPrev){prevURL = varPrev;}

    @Column(name = "modelNo")
    public String getModelNo(){return modelNo;}

    @Id
    @Column(name = "VIN")
    public String getVIN(){return VIN;}

    @Column(name = "model")
    public String getModel(){return model;}

    @Column(name = "make")
    public String getMake(){return make;}

    @Column(name = "type")
    public String getType(){return type;}

    @Column(name = "thumbnail")
    public String getThumbnail(){return thumbnail;}

    @Column(name = "description")
    public String getDesc(){return description;}

    @Column(name = "prevURL")
    public String getPrevURL(){return prevURL;}
}

据我了解,我应该可以添加以下行:

public class CarSales 
{
    @EJB
    private static CarRepository carRepo;

到处理我的业务逻辑的企业应用程序客户端中的类,然后我应该能够调用其CarRepositoyImpl bean中的方法来访问数据库。 我很确定我不应该像普通对象那样实例化carRepo对象,因为EJB容器应该处理该对象。

本质上,我希望能够像这样在我的Application客户端中使用我的无状态bean:

List<Car> cars = carRepo.getAllCars();

但是当我这样做时,它会引发一个空指针异常,我也不知道为什么。

目前,我的应用程序客户端类目前尚不完整:

public class CarSales 
{
    @EJB
    private static CarRepository carRepo;

    private final MainScreen main;

    public CarSales()
    {
        main = new MainScreen();
        addCarActionListeners();
    }

    public void run()
    {
        displayAllCars();
    }

    private void displayAllCars()
    {
        main.getCarScreen().clearTable();

        try
        {
            List<Car> cars = carRepo.getAllCars();

            for(Car car : cars)
            {//"VIN", "Model Number", "Model Name", "Make", "Thumbnail", "Description", "URL"
                String[] data = new String[7];
                data[0] = car.getVIN();
                data[1] = car.getModelNo();
                data[2] = car.getModel();
                data[3] = car.getMake();
                data[4] = car.getThumbnail();
                data[5] = car.getDesc();
                data[6] = car.getPrevURL();
                main.getCarScreen().getModel().addRow(data);
            }
        }
        catch(Exception ex)
        {
            main.getCarScreen().outputAddError(ex.getMessage());
            System.out.println("failed");
            ex.printStackTrace();
        }
    }

    private void addCarActionListeners()
    {//CLOSE
        main.getCarScreen().getClose().addActionListener(new ActionListener()
        {
            @Override
            public void actionPerformed(ActionEvent e)
            {
                main.closeWindow();
            }
        });

        main.getCarScreen().getAdd().addActionListener(new ActionListener()
        {
            @Override
            public void actionPerformed(ActionEvent e)
            {
                Car car = new Car(main.getCarScreen().getModelNo(), 
                            main.getCarScreen().getVin(),
                            main.getCarScreen().getModelName(),
                            main.getCarScreen().gerMake(),
                            main.getCarScreen().getType(),
                            main.getCarScreen().getThumb(),
                            main.getCarScreen().getDesc(),
                            main.getCarScreen().getUrl());
                try
                {
                    System.out.println("try");
                    carRepo.addCar(car);
                    displayAllCars();
                }
                catch(Exception ex)
                {
                    System.out.println("catch");
                    //main.getCarScreen().outputAddError(ex.getMessage());
                    System.out.println(ex.getMessage());
                }
            }
        });
    }
}

我的错误的堆栈跟踪:

java.lang.NullPointerException
at CarSales.CarSales.displayAllCars(CarSales.java:45)
at CarSales.CarSales.run(CarSales.java:36)
at CarSales.Main.main(Main.java:18)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.glassfish.appclient.client.acc.AppClientContainer.launch(AppClientContainer.java:446)
at org.glassfish.appclient.client.AppClientFacade.main(AppClientFacade.java:166)

45行是:

List<Car> cars = carRepo.getAllCars();

对我的CarSales类进行了一些建议的更改:

public class CarSales 
{
    @EJB
    private CarRepository carRepo;

    private final MainScreen main;

    public CarSales()
    {
        main = new MainScreen();
    }

    @PostConstruct
    public void init() 
    {
        addCarActionListeners();
    }

    public void run()
    {
        displayAllCars();
    }

我调用的主要函数运行:

public class Main 
{
    public static void main(String[] args) 
    {
        CarSales sys = new CarSales();
        sys.run();
    }
}

如果您自己创建对象,则容器将没有机会执行注入。 在客户端容器中,实际上只有主类才有资格进行注入。 尝试:

public class Main 
{
    @EJB
    private static CarRepository carRepo;

    public static void main(String[] args) 
    {
        CarSales sys = new CarSales(carRepo);
        sys.run();
    }
}

public class CarSales 
{
    private final CarRepository carRepo;
    private final MainScreen main;

    public CarSales(CarRepository carRepo)
    {
        this.carRepo = carRepo;
        main = new MainScreen();
    }

或者,您可以在主类中声明该引用,然后从客户端应用程序中的任何位置查找EJB引用:

@EJB(name="ejb/carRepo", beanInterface=CarRepository.clas)
public class Main 
{
    public static void main(String[] args)

...
CarRepository carRepo = (CarRepository)new InitialContext().lookup("java:comp/env/ejb/carRepo");

根据您编写的内容,我假设您正在尝试在CarSales构造函数中调用carRepo.getAllCars() 您无法在此处执行此操作。 而是在用PostConstruct注释的方法中执行此操作。

您应该这样做:

public CarSales() {
    main = new MainScreen();
}

@PostConstruct
public void init() {
   addCarActionListeners();
}

确定再编辑一次。 为什么将注入的bean标记为static 不应该那样做。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM