单身人士的范围

时间:2014-09-09 05:51:36

标签: java rest singleton jboss7.x java-ee-6

我正在使用单例bean将存储在数据库中的配置值提供给我的Java EE应用程序。

@Singleton
public class ConfigurationProvider {

  private final Map<String, ConfigurationEntity> configMap = new HashMap<>();

  @PersistenceContext(unitName = DatabaseConstants.PERSISTENCE_UNIT)
  private EntityManager em;

  public String getConfiguration(String key) {
    if (configMap.containsKey(key)) {
        return configMap.get(key).getValue();
    }

    ConfigurationEntity config = em.find(ConfigurationEntity.class, key);
    em.detach(config);
    if (config == null) {
        throw new RuntimeException("Configuration not found for " + key);
    }
    configMap.put(key, config);
    return config.getValue();
  }

  public void clear() {
    configMap.clear();
  }

  public Collection<ConfigurationEntity> getCurrentConfigurationState() {
    return configMap.values();
  }
 }

生产者让我注入值

public class ConfigurationProducer {

  @Inject
  private ConfigurationProvider configProvider;

  @Produces
  @ConfigurationValue
  public String getConfiguration(InjectionPoint ip) {
    String key = createKey(ip);
    return configProvider.getConfiguration(key);
  }

这是一个例子

@Inject
@ConfigurationValue
private Instance<String> endpoint;

这会从数据库加载endpont。出于测试原因,该值应该是可更改的。 所以你看到的是ejb模块的一部分。

为了重新加载这些值,我创建了一个提供该功能的REST接口。此REST服务是与ejb模块一起打包在一个ear文件中的附加WAR的一部分。

@Path("/configuration")
public class ConfigurationResource {

  @EJB
  private ConfigurationProvider configurationProvider;

  @GET
  @Path("/current")
  @Produces({ "application/json" })
  public Collection<ConfigurationEntity> getCurrentConfiguration() {
    return configurationProvider.getCurrentConfigurationState();
  }
}

但问题是,战争有它自己的配置提供者实例。所以我无法实现'缓存'。 为什么我的同一个耳中有两个单身实例?

3 个答案:

答案 0 :(得分:0)

我认为你不能以这种方式使用ConfigurationProvider EJB。 EJB需要具有远程接口,您可以从外部WAR访问它作为任何远程EJB。外部WAR具有不同的类加载器,因此它不会找到EAR单例EJB。

答案 1 :(得分:0)

您似乎正在使用CDI的@Inject和EJB的@EJB来注入您的ConfigurationProvider实例。考虑到你没有同步访问map并且你正在使用不是线程安全的EntityManager,你应该使用@EJB。

也就是说,您只需要对代码进行一些小改动:

public class ConfigurationProducer {
    @EJB
    private ConfigurationProvider configProvider;

    @Produces
    @ConfigurationValue
    public String getConfiguration(InjectionPoint ip) {
        String key = createKey(ip);
        return configProvider.getConfiguration(key);
}

答案 2 :(得分:0)

解决方案:

Maven第二次在war的lib文件夹中打包了ejb模块。我必须在pom.xml中设置范围才能提供。使用ejb模块,它可以毫无排除地运行,但对于战争,你必须手动完成。

现在可行。