2017-01-15 11 views
1

В настоящее время я работаю над приложением Java EE 7 Batch API, и мне бы хотелось, чтобы жизненный цикл одного из моих CDI Bean был связан с текущим заданием. На самом деле я бы хотел, чтобы этот компонент имел область @JobScoped (но она не существует в API). Также я хотел бы, чтобы этот компонент был инъекционным в любом из моих классов.Java EE 7 Batch API: создание рабочей области CDI Bean

Сначала я хотел создать свою собственную @JobScoped сферы, с JobScopedContext и т.д. Но потом я пришел с идеей, что Batch API имеет JobContext боб с уникальным идентификатором задания на боб.

Так что я задаюсь вопросом, могу ли я управлять жизненным циклом моей работы с фасолью с этим JobContext.

К примеру, я бы мой боб, что я хочу быть работа областью действия:

@Alternative 
public class JobScopedBean 
{ 
    private String m_value; 

    public String getValue() 
    { 
     return m_value; 
    } 

    public void setValue(String p_value) 
    { 
     m_value = p_value; 
    } 
} 

Тогда я бы продюсером этого боба, который возвратит JobScopedBean, связанный с текущим заданием (благодаря JobContext, который является уникальным для каждого задания)

public class ProducerJobScopedBean 
{ 

    @Inject 
    private JobContext m_jobContext;// this is the JobContext of Batch API 

    @Inject 
    private JobScopedManager m_manager; 

    @Produces 
    public JobScopedBean getObjectJobScoped() throws Exception 
    { 
     if (null == m_jobContext) 
    { 
     throw new Exception("Job Context not active"); 
     } 

     return m_manager.get(m_jobContext.getExecutionId()); 
    } 
} 

И менеджер, который держит карту моего JobScopedBean:

@ApplicationScoped 
public class JobScopedManager 
{ 
    private final ConcurrentMap<Long, JobScopedBean> mapObjets = new ConcurrentHashMap<Long, JobScopedBean>(); 

    public JobScopedBean get(final long jobId) 
    { 
     JobScopedBean returnObject = mapObjets.get(jobId); 
     if (null == returnObject) 
     { 
     final JobScopedBean ajout = new JobScopedBean(); 
     returnObject = mapObjets.putIfAbsent(jobId, ajout); 

     if (null == returnObject) 
     { 
      returnObject = ajout; 
     } 
     } 
     return returnObject; 
    } 

Конечно, я буду уничтожать JobScopedBean в конце каждого задания (через JobListener и CDI Event).

Можете ли вы сказать мне, если я ошибаюсь в этом решении?

Это выглядит правильно, но, может быть, я что-то упустил?

Может быть, есть лучший способ справиться с этим?

Спасибо.

ответ

1

Таким образом, это сводится к созданию бонусов @Dependent, основанных на задании на создание. Прекрасно работает для beans со сроком службы меньше, чем задание, поэтому для стандартных областей только @Dependent (@ Request/@ Session/@ Converstion может быть в порядке, но не применяется здесь).

Это вызовет проблемы для других областей применения, особенно @ ApplicationScoped/@ Singleton. Если вы введете JobScopedBean в один из них. Вам может быть (un) повезло, что у вас есть активная работа, когда вы в них нуждаетесь в первый раз, но бобы всегда будут прикреплены к этому начальному заданию (объекты @Dependent scope не являются псевдоскопическими, поэтому не будут создавать прокси для получения контекстного экземпляра)

Если вы хотите что-то подобное, создайте таможню.

+0

Спасибо @ k5_. Это был тот момент, который я пропустил, позор мне! Конечно, проблема заключается в @ApplicationScoped beans (на самом деле даже инъекция 'JobContext' в компоненте @ApplicationScoped будет иметь проблемы с тем, что введенный bean-компонент будет зависеть от @ApplicationScoped bean-компонента). Спасибо, что указал на проблему в моем решении, я знал, что что-то не так, но я не мог понять. – Rouliboy

+0

Я дам попробовать пользовательскую область CDI, которая кажется единственным способом достичь этого. – Rouliboy