1> TÓM TẮT
Ban đầu, tôi đã thử cách ly tải lớp này để tải các khay Hibernate 3.6.4 với JBoss 5.1.0.GA.
Hoàn toàn KHÔNG thể thực hiện được. Có một số ma thuật dưới mui xe ngăn bạn sử dụng bất kỳ phiên bản Hibernate nào có hỗ trợ JPA2.
Tôi thực sự thất vọng rằng dự án JBoss không cung cấp một số loại bản vá hoặc gói dịch vụ để hỗ trợ JPA2 trên 5.1.0.GA.
2> CÁCH GIẢI QUYẾT: "The Kernel giải pháp"
tôi đã quản lý để sử dụng JPA2 với JBoss 5.1.0.GA tôi mô tả ở đây công thức nấu ăn của tôi. Nó là một bằng chứng về khái niệm bạn có thể sử dụng để làm cho giải pháp của riêng bạn.
Thành phần:
- 1 WAR lưu trữ
- 1 servlet
- 1 ứng dụng độc lập java (J2SE)
Recipe:
Bước 1: Xây dựng ứng dụng độc lập (APP)
Ứng dụng này sẽ nhận được hướng dẫn từ servlet để sử dụng Hibernate.
Tôi để bạn lựa chọn phương thức liên lạc. Khi APP sử dụng JPA2, nó sẽ cần tệp persistence.xml
nằm trong thư mục META-INF
. Kể từ JBoss 5.x, khi bạn triển khai một WAR, JBoss sẽ quét WAR và tất cả các triển khai phụ của nó để tìm và triển khai các tệp persistence.xml
mù quáng. Đổi tên tệp persistence.xml
của bạn thành my-persistence.xml
chẳng hạn. Sử dụng mã bên dưới khi bạn xây dựng EntityManagerFactory
(Ngăn JBoss triển khai persistence.xml).
CẬP NHẬT: Phương pháp này hoạt động nhưng một số cảnh báo lạ được nâng lên bởi Hibernate. Để ngăn chặn những cảnh báo đó, tôi đã quyết định đặt thư mục META-INF
và tệp kiên trì (được đổi tên thành persistence.xml
bây giờ) bên ngoài WAR. Trong trường hợp của tôi, tôi đã chọn một thư mục cấu hình đặc biệt trên ổ cứng và thêm nó vào đường dẫn lớp. Không có cảnh báo lạ hơn và không có trình nạp lớp tùy chỉnh cần thiết để tải tệp kiên trì.
Tôi để bạn tùy chọn giữa việc sử dụng trình tải lớp tùy chỉnh hoặc thay đổi vị trí tệp kiên trì. Trong cả hai trường hợp, JBoss sẽ không tìm thấy tệp kiên trì.
Bước 2: Xây dựng các servlet
Khi servlet cần phải truy cập vào cơ sở dữ liệu, nó sẽ khởi động APP và nói với nó làm gì.
Để phát tán APP, servlet chịu trách nhiệm sinh sản một JVM mới và xây dựng đường dẫn lớp của APP. Đọc mã bên dưới để (Tạo một JVM). Classpath là dễ dàng thể xây dựng từ tất cả các lọ cần sẽ nằm trong thư mục /lib
của các kho lưu trữ WAR ...
Bước 3: Xây dựng các kho lưu trữ WAR
Xây dựng một kho lưu trữ WAR nơi bạn đặt servlet và ứng dụng độc lập được đóng gói như một JAR. APP sẽ là phụ thuộc của WAR.
Ngăn chặn JBoss từ triển khai persistence.xml
// Install a proxy class loader for adding renamed persistence.xml file
Thread t = Thread.currentThread();
ClassLoader clOriginal = t.getContextClassLoader();
t.setContextClassLoader(new SpecialClassLoader(clOriginal, "META-INF/my-persistence.xml"));
// Build EntityManagerFactory
EntityManagerFactory emf = Persistence.createEntityManagerFactory(persistenceUnitName);
// Restore original class loader
t.setContextClassLoader(clOriginal);
//...
private class ProxyClassLoader extends ClassLoader {
private ClassLoader realClassLoader;
private String hiddenFromJBossPersistenceFile;
public ProxyClassLoader(ClassLoader realClassLoader, String hiddenFromJBossPersistenceFile) {
this.realClassLoader = realClassLoader;
this.hiddenFromJBossPersistenceFile = hiddenFromJBossPersistenceFile;
}
public void clearAssertionStatus() {
realClassLoader.clearAssertionStatus();
}
public boolean equals(Object obj) {
return realClassLoader.equals(obj);
}
public URL getResource(String name) {
return realClassLoader.getResource(name);
}
public InputStream getResourceAsStream(String name) {
return realClassLoader.getResourceAsStream(name);
}
public Enumeration<URL> getResources(String name) throws IOException {
ArrayList<URL> resources = new ArrayList<URL>();
if (name.equalsIgnoreCase("META-INF/persistence.xml")) {
resources.add(getResource(this.hiddenFromJBossPersistenceFile));
}
resources.addAll(Collections.list(realClassLoader.getResources(name)));
return Collections.enumeration(resources);
}
public int hashCode() {
return realClassLoader.hashCode();
}
public Class<?> loadClass(String name) throws ClassNotFoundException {
return realClassLoader.loadClass(name);
}
public void setClassAssertionStatus(String className, boolean enabled) {
realClassLoader.setClassAssertionStatus(className, enabled);
}
public void setDefaultAssertionStatus(boolean enabled) {
realClassLoader.setDefaultAssertionStatus(enabled);
}
public void setPackageAssertionStatus(String packageName, boolean enabled) {
realClassLoader.setPackageAssertionStatus(packageName, enabled);
}
public String toString() {
return realClassLoader.toString();
}
}
đẻ trứng một JVM
public static Process createProcess(final String optionsAsString, final String workingDir, final String mainClass, final String[] arguments) throws IOException {
String jvm = System.getProperty("java.home") + File.separator + "bin" + File.separator + "java";
String[] options = optionsAsString.split(" ");
List<String> command = new ArrayList<String>();
command.add(jvm);
command.addAll(Arrays.asList(options));
command.add(mainClass);
command.addAll(Arrays.asList(arguments));
//System.out.println(command);
ProcessBuilder processBuilder = new ProcessBuilder(command);
processBuilder.directory(new File(workingDir));
return processBuilder.start();
}
public static void makeItRun() {
try {
// Start JVM
String classPath = buildClassPath();
String workingDir = getSuitableWorkingDir();//or just "."
Process java = createProcess("-cp \"" + classPath + "\"", workingDir, my.package.APP.class.getCanonicalName(), "-the -options -of -my -APP");
// Communicate with your APP here ...
// Stop JVM
java.destroy();
} catch(Throwable t) {
t.printStackTrace();
}
}
Làm thế nào để bạn biết nó đang sử dụng các lọ riêng? – gkamal
@gkamal Khi ứng dụng của tôi chạy, tôi nhận được một ngoại lệ 'NoSuchMethod'. – Stephan
WAR có được triển khai riêng hay là một phần của EAR không? – CoolBeans