2016-05-25 5 views
0

Я пытаюсь сделать что-то вроде следующего:Как создать общий производитель для квалифицированных и расширенных CDI-компонентов?

@Qualifier 
@Retention(RUNTIME) 
@Target({ PARAMETER, FIELD, METHOD, TYPE }) 
public @interface ForQueueName{ 
    String value(); 
} 

public class JmsSenderProducer { 
    @Produces 
    @Any 
    @ApplicationScoped 
    public JmsSender createJmsSender(InjectionPoint ip) { 
     ForQueueName annotation = ip.getAnnotated().getAnnotation(ForQueueName.class); 
     return new JmsSender(annotation.value()); 
    } 
} 

// Somewhere else 
@Inject 
@ForQueueName("java:/jms/queue/my.queue.name") 
JmsSender myQueueSender; 

Конечно, это не работает, потому что

  1. @Any не работает в качестве замены для любой квалифицированный @ForQueueName
  2. InjectionPoint не могут быть использованы при изготовлении фасоли @ApplicationScoped.

Я знаю, что мог бы создать @Dependent фасоль с непереплетным классификатором таким образом. Но в моем случае я действительно нуждаюсь в не зависимом объекте.

Возможно ли что-то подобное? Если нет, есть ли какая-то особая причина?

Приветствия, Tilmann

EDIT: Fixed имя сфера из @Default в @Dependent

+0

Для того, чтобы это было возможно, спецификация должна была бы предоставить другой объект вместо «InjetctionPoint», который обеспечивает доступ только к указанным квалификаторам инъекции. – Gandalf

ответ

0

Во-первых, вы должны рассмотреть возможность использования JMSContext в вашем приложении. Его JMS 2.0 имеет гораздо более чистый API.

Во-вторых, ваш метод производителя должен быть аннотирован ForQueueName. Для этого необходимо указать атрибут value()ForQueueName, который должен быть помечен как @Nonbinding. Это сообщает контейнеру CDI, что значение не следует учитывать при поиске производителя.

@Qualifier 
@Retention(RUNTIME) 
@Target({ PARAMETER, FIELD, METHOD, TYPE }) 
public @interface ForQueueName{ 
    @Nonbinding String value(); 
} 

public class JmsSenderProducer { 
    @Produces 
    @ForQueueName("") 
    @Dependent // must be dependent to interrogate the injection point 
    public JmsSender createJmsSender(InjectionPoint ip) { 
     ForQueueName annotation = ip.getAnnotated().getAnnotation(ForQueueName.class); 
     return new JmsSender(annotation.value()); 
    } 
} 

// Somewhere else 
@Inject 
@ForQueueName("java:/jms/queue/my.queue.name") 
JmsSender myQueueSender; 
+0

На самом деле я сделал это сначала. (См. Второе последнее предложение в моем вопросе.) Но этот подход не позволяет мне использовать beans '@ ApplicationScoped'. JMS был всего лишь примером, у меня также есть другие случаи. Но, в любом случае, спасибо тем, кто сталкивается, и ищут для создания факсимильных объектов '@ Default' :) – Gandalf

+0

Догадка, что я не приду, чтобы написать отдельный класс компонентов или метод производителя для каждой очереди, которую я хотел бы адресовать. Я надеялся избежать этого, поскольку это как-то противоречит открытому закрытому принципу. Возможно, есть еще один, но менее красивый способ сделать это с помощью менеджера bean или в качестве защищаемого расширения. Но опять же усилия не окупятся. – Gandalf

+0

Извините, я перепутал имя области и использовал '@ Default' вместо' @ Dependent'. Я редактировал сообщение. – Gandalf

Смежные вопросы