Java EE-webservice中的线程安全

Java EE-webservice中的线程安全,java,multithreading,web-services,Java,Multithreading,Web Services,阅读: “在WAR中部署的带有@WebService注释的POJO..不是线程安全的” 实际上,“EJB(注释为@webservice)在默认情况下是线程安全的” 我有一个疑问,我的公司使用pojo注释的@Webservice(打包在战争中),它使用@EJB组件(打包在JAR中),所有组件都包装在一个EE应用程序“.ear”中 所有逻辑都在ejb组件内,但是存储在ejb内的类变量是线程安全的吗 我必须实现一个代理Web服务,它并行调用其他Web服务并收集所有响应,对它们进行排序并返回给调用方 我

阅读:

“在WAR中部署的带有@WebService注释的POJO..不是线程安全的” 实际上,“EJB(注释为@webservice)在默认情况下是线程安全的”

我有一个疑问,我的公司使用pojo注释的@Webservice(打包在战争中),它使用@EJB组件(打包在JAR中),所有组件都包装在一个EE应用程序“.ear”中

所有逻辑都在ejb组件内,但是存储在ejb内的类变量是线程安全的吗

我必须实现一个代理Web服务,它并行调用其他Web服务并收集所有响应,对它们进行排序并返回给调用方

我该如何认识到这一点?我将在代理服务器中使用线程安全的hashmap来收集以异步方式调用其他web服务的临时响应(例如,使用jax-ws回调机制)

这条路对吗

编辑:

@WebService(serviceName=“ProxyWS”) 公共类代理{

@EJB
private ProxyBeanLocal proxyBean;

@WebMethod(operationName = "hello")
public String hello(@WebParam(name = "name") String txt) {
    return proxyBean.businessMethod();
}
}

@无状态
公共类ProxyBean实现ProxyBeanLocal{
专用最终字符串适配器_1_URL=“”;
专用最终字符串适配器_2_URL=“”;
并行映射m;
@凌驾
公共字符串businessMethod(){
试一试{
m=新的ConcurrentHashMap();
适配器服务适配器=新适配器服务(新URL(适配器1 URL));
AdapterWSAdapter=serviceAdapter.getAdapterSport();
helloAsync(“,this);//调用异步并对此进行回调
serviceAdapter=新适配器服务(新URL(适配器2\U URL));
adapter=serviceAdapter.getAdapterSport();
adapter.helloAsync(“,this”);
}捕获(格式错误){
Logger.getLogger(ProxyBean.class.getName()).log(Level.SEVERE,null,ex);
}
return null;//所有响应到达后返回记录集(使用阻塞队列?)
}
@凌驾
公共无效处理响应(响应res){
试一试{
m、 put(res.get().getReturn(),res.get().getReturn());
}捕获(中断异常例外){
Logger.getLogger(ProxyBean.class.getName()).log(Level.SEVERE,null,ex);
}捕获(ExecutionException ex){
Logger.getLogger(ProxyBean.class.getName()).log(Level.SEVERE,null,ex);
}
}

}

可以从不同的线程调用用
@WebService
注释的端点实现。以下是报告的相关部分:

通常会调用端点来服务并发请求,因此 它的实现程序应该编写为支持多线程。 synchronized关键字可以像往常一样用于控制对 代码的关键部分

如果您想要一个类型为
ConcurrentMap
的类变量,那么如果预期映射应该包含来自客户端的一个特定调用的处理结果,那么这可能不适用于您。原因是,如果同时处理两个调用,那么来自这两个调用的数据将进入该映射。即使这不会破坏底层映射的结构,返回的数据也很可能是不一致的(比如来自两个请求的数据的混合)

您需要将数据与正在运行的其他请求隔离开来。而类变量并没有做到这一点。堆栈变量或线程本地应该这样做。还可能存在如何从WebService1…WebServiceN获取数据的问题。如果这是在其他线程中完成的,那么您需要同步对该原因映射的访问,但这不是并发问题的一部分

想想如果两个客户端同时调用
hello
端点和
businessMethod
会发生什么。来自服务的响应将放在
handleResponse
中相同的
ConcurrentHashMap

克服此问题的一种方法是创建
asynchHandler
,它将引用为处理特定请求而创建的映射,如下所示:

public static ResponsesCollector implements AsyncHandler<HelloResponse> {
   private Map<String, String> responses = new ConcurrentHashMap<>();
   @Override
   public void handleResponse(Response<HelloResponse> res) {
      responses.put(res.get().getReturn(), res.get().getReturn());
   }
   public Map<String, String> getResponses() {
      return responses; 
   }
}


@Override
public String businessMethod() {

    try {
        ResponsesCollector responsesCollector = new ResponsesCollector()

        AdapterWS_Service serviceAdapter = new AdapterWS_Service(new URL(ADAPTER_1_URL));
        AdapterWS adapter = serviceAdapter.getAdapterWSPort();

        adapter.helloAsync("", responsesCollector);

        serviceAdapter = new AdapterWS_Service(new URL(ADAPTER_2_URL));
        adapter = serviceAdapter.getAdapterWSPort();

        adapter.helloAsync("", responsesCollector);

    } catch (MalformedURLException ex) {
        Logger.getLogger(ProxyBean.class.getName()).log(Level.SEVERE, null, ex);
    }

    // ideally here you need return control to container
    // and resume processing inside responseCollector
    // when the last response is gotten. The problem is that JAX-WS does not
    // specify how to do async processing on server side (similar to Async Servlets in Servlets specification 3.x).
    // I know only one implementation that has an extension for async WebMethod -
    // JEUS, see https://technet.tmaxsoft.com/upload/download/online/jeus/pver-20160610-000001/web-service/chapter_jaxws_async_operation.html
    // So the only portable option here is to wait (using container thread).

    // 

    return null; //return recordset once all responses arrived (using blocking queue?)

}
公共静态响应Collector实现AsyncHandler{
私有映射响应=新的ConcurrentHashMap();
@凌驾
公共无效处理响应(响应res){
responses.put(res.get().getReturn(),res.get().getReturn());
}
公共映射getResponses(){
回应;
}
}
@凌驾
公共字符串businessMethod(){
试一试{
ResponseCollector ResponseCollector=新的ResponseCollector()
适配器服务适配器=新适配器服务(新URL(适配器1 URL));
AdapterWSAdapter=serviceAdapter.getAdapterSport();
adapter.helloAsync(“,ResponseCollector);
serviceAdapter=新适配器服务(新URL(适配器2\U URL));
adapter=serviceAdapter.getAdapterSport();
adapter.helloAsync(“,ResponseCollector);
}捕获(格式错误){
Logger.getLogger(ProxyBean.class.getName()).log(Level.SEVERE,null,ex);
}
//理想情况下,您需要对容器进行返回控制
//并在responseCollector内恢复处理
//问题是JAX-WS没有
//指定如何在服务器端执行异步处理(类似于servlet规范3.x中的异步servlet)。
//我只知道一个实现具有异步WebMethod的扩展-
//杰斯,看https://technet.tmaxsoft.com/upload/download/online/jeus/pver-20160610-000001/web-service/chapter_jaxws_async_operation.html
//所以这里唯一的可移植选项是等待(使用容器线程)。
// 
return null;//所有响应到达后返回记录集(使用阻塞队列?)
}

谢谢,我添加了一个示例以更好地理解我将要做的事情。你认为这会导致不一致吗?是的,这个实现有我在回答中描述的问题。我已经添加了一个如何解决这个问题的想法的草图@FrancescoUmani
public static ResponsesCollector implements AsyncHandler<HelloResponse> {
   private Map<String, String> responses = new ConcurrentHashMap<>();
   @Override
   public void handleResponse(Response<HelloResponse> res) {
      responses.put(res.get().getReturn(), res.get().getReturn());
   }
   public Map<String, String> getResponses() {
      return responses; 
   }
}


@Override
public String businessMethod() {

    try {
        ResponsesCollector responsesCollector = new ResponsesCollector()

        AdapterWS_Service serviceAdapter = new AdapterWS_Service(new URL(ADAPTER_1_URL));
        AdapterWS adapter = serviceAdapter.getAdapterWSPort();

        adapter.helloAsync("", responsesCollector);

        serviceAdapter = new AdapterWS_Service(new URL(ADAPTER_2_URL));
        adapter = serviceAdapter.getAdapterWSPort();

        adapter.helloAsync("", responsesCollector);

    } catch (MalformedURLException ex) {
        Logger.getLogger(ProxyBean.class.getName()).log(Level.SEVERE, null, ex);
    }

    // ideally here you need return control to container
    // and resume processing inside responseCollector
    // when the last response is gotten. The problem is that JAX-WS does not
    // specify how to do async processing on server side (similar to Async Servlets in Servlets specification 3.x).
    // I know only one implementation that has an extension for async WebMethod -
    // JEUS, see https://technet.tmaxsoft.com/upload/download/online/jeus/pver-20160610-000001/web-service/chapter_jaxws_async_operation.html
    // So the only portable option here is to wait (using container thread).

    // 

    return null; //return recordset once all responses arrived (using blocking queue?)

}