我对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容器应该处理它。
基本上我希望能够在我的应用程序客户端中使用我的无状态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();
}
我的主要功能是调用run:
public class Main
{
public static void main(String[] args)
{
CarSales sys = new CarSales();
sys.run();
}
}
答案 0 :(得分:1)
如果您自己创建对象,则容器无法执行注入。在客户端容器中,实际上只有主类符合注入条件。尝试:
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");
答案 1 :(得分:0)
根据您所写的内容,我假设您尝试在carRepo.getAllCars()
构造函数中调用CarSales
。你不能在那里做到这一点。请在使用PostConstruct
注释的方法中执行此操作。
你应该这样做:
public CarSales() {
main = new MainScreen();
}
@PostConstruct
public void init() {
addCarActionListeners();
}
确定再编辑一次。
为什么注入的bean标记为static
?不应该这样做。