Java EJB到JNI(C+;+;)调用

Java EJB到JNI(C+;+;)调用,java,java-native-interface,ejb,ejb-3.0,weblogic-10.x,Java,Java Native Interface,Ejb,Ejb 3.0,Weblogic 10.x,我正在尝试使用JNI从EJB调用windows上的本机库(dll)。我读过很多博客,网站建议EJB规范中不允许从EJB进行JNI调用。不过也有特定于供应商的例外情况。我使用weblogic作为EJB容器。如果你能在这方面给我提供指导/建议。我知道资源适配器是一种选择,但对于简单的需求来说,实现它是一项艰巨的任务。这是我的方法 我开发了一个简单的JNI,它调用C++本地库(也由我构建)并输出输出: 类JNI类HeloJiNCPP调用DLL,调用一个原生方法 SayelLoor()/St>>,用C

我正在尝试使用JNI从EJB调用windows上的本机库(dll)。我读过很多博客,网站建议EJB规范中不允许从EJB进行JNI调用。不过也有特定于供应商的例外情况。我使用weblogic作为EJB容器。如果你能在这方面给我提供指导/建议。我知道资源适配器是一种选择,但对于简单的需求来说,实现它是一项艰巨的任务。这是我的方法

我开发了一个简单的JNI,它调用C++本地库(也由我构建)并输出输出:

类JNI类HeloJiNCPP调用DLL,调用一个原生方法<强> SayelLoor()/St>>,用C++实现,输出为

现在,我实现了一个会话bean(TestEJBBean.java),一个由bean调用的包装类HelloJNICpp.java(如JNI)。最后是一个独立的java客户机TestEJBClient.java来测试bean,测试它是否可以被调用,是否可以调用本机

以下是代码详细信息:

远程接口

package com.test.services;

import javax.ejb.Remote;

@Remote
public interface TestEJBRemote {
    public  void helloJNI();
}
会话Bean

package com.test.services;

import javax.ejb.Stateless;

@Stateless(mappedName = "TestEJB")
public class TestEJBBean implements TestEJBRemote {
    public void helloJNI(){
        new HelloJNICpp(). hello();  // Invoke native method
        }
}
包装类充当JNI

package com.test.services;

public class HelloJNICpp {

static {
      //System.load("hellocpp"); // hello.dll (Windows) or libhello.so (Unixes)
     try{
     System.loadLibrary("hellocpp");
     }catch( Exception e){
         System.out.println("Some problem occurred while loading library.");
     }
   }    

   // Native method declaration
   private native void sayHello();

   // Test Driver
   public static void hello() {
      new HelloJNICpp().sayHello();  // Invoke native method

   }
}
Bean测试客户端

package com.test.client;

import com.test.services.*;
import java.util.Hashtable;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;

public class TestEJBClient {
public static void main (String args[]){
try {
        Context ctx = new InitialContext(getInitialContext());
        TestEJBRemote testBean = (TestEJBRemote) ctx.lookup("TestEJB#com.test.services.TestEJBRemote");
         testBean.helloJNI();
    } catch (NamingException e) {
        e.printStackTrace();
    }
}

     private static Hashtable<String, Object> getInitialContext() {
        Hashtable<String, Object> properties = new Hashtable<String, Object>();
        properties.put(Context.INITIAL_CONTEXT_FACTORY, "weblogic.jndi.WLInitialContextFactory");
        properties.put(Context.PROVIDER_URL, "t3://localhost:7001");
        return properties;
    }
}
以下是项目结构:

JNIEXPORT void JNICALL Java_com_test_services_HelloJNICpp_sayHello (JNIEnv *env, jobject thisObj)

从EJB调用/加载本机库在技术上是不可能的,还是我遗漏了什么?我确信塔尔静态块没有抛出任何异常,因为它有一个try-catch块,并且在weblogic级别没有捕获任何异常


提前感谢。

我从各个角度进行了调查,记住了所有方面,最终能够解决问题。我从技术上理解,从会话bean(部署在Weblogic上)调用JNI库是可能的,但是从EJB规范的角度来看,这可能不是一种建议的做法,因为本机库调用使bean系统依赖于它,并且它不再具有可移植性

由于UnsatifiedLinkError具有多种性质,因此

 java.lang.UnsatisfiedLinkError: com.test.services.HelloJNICpp.sayHello()V
看起来运行时JNI绑定失败了。我采取的解决问题的方法:

检查java.library.path-

按照朋友们的建议,我写了

System.getProperty("java.library.path") 
在bean中,确保我的dll已经存在。在我的例子中,它是OS库加载路径C:/Windows/System32(尽管我在执行JNI的本地实践文件夹中也有这个库)

检查文件夹权限 包含本机库的文件夹也具有读写执行权限

容器库路径

我将库放在[WEBLOGIC\u HOME]/server/lib中,这样在运行时容器就可以启动了。即使这样也不能解决问题

JNI签名 我想重温我的JNI头文件和本机实现。我在创建头文件(HelloJNICpp.h)时发现,源JAVA类不包含package语句。后来我加入了package语句,以便从Eclipse运行它。这是一个问题,是我自己的代码。最初是这样的:

JNIEXPORT void JNICALL Java_HelloJNICpp_sayHello (JNIEnv *env, jobject thisObj)
使用适当的包结构创建之后:

JNIEXPORT void JNICALL Java_com_test_services_HelloJNICpp_sayHello (JNIEnv *env, jobject thisObj)
这就成功了!我的学习:

  • 因此,在使用JNI代码时必须采取额外的预防措施 具有封装结构
  • java.library.path属性是JNI中的游戏规则改变者
  • EclispeJava运行时和JNI的运行时必须相同
  • 对于C++,我注意到我还必须放置一些依赖于系统的库。 java.library.path与我的本机库不同。它们被用来链接MinGW编译器套件。它们可以通过运行来跟踪 依赖沃克

  • EJB应该通过JCA资源适配器调用本机代码


    JNI-RA-HOWTO中有一个示例:

    您的库是否位于-Djava.library.path上?在ejb方法中调用
    System.getProperty(“java.library.path”)
    。也许它被某种方式覆盖了……IIRC,在JVM加载DLL之前,您需要授予DLL权限。@xwid正如我所提到的,“java.libry.path”是我的C:\Windows\System32文件夹,我也放在了服务器库中。@AlexBarker我已经授予DLL完全权限,仍然是相同的错误。DLL和文件夹的任何其他标识都需要权限。此外,您显示的屏幕截图显示了C:\practice中的hellocpp.dll文件,该文件不是C:\Windows\System32。java.library.path属性告诉java在哪里查找System.load引用的JNI库。。。这与操作系统库加载路径不同!请遵循xwid的建议并检查java.library.path。我怀疑您忘记设置该属性或将其设置为不正确的值。