2016-09-01 3 views
1

У меня есть приложение, состоящее из войн, основного ejb с большим количеством сервисов в банке и удаленных интерфейсах в другой банке. Все упаковано в ухо и работает на Glassfish 4.1.Плагин Java EE с использованием CDI Instance Iterator

Теперь я хочу добавить дополнительные точки или плагиновую поддержку ядра ejb.

Цель состоит в том, чтобы иметь разные услуги импорта данных с возможностью горячей замены, которые все используют один и тот же интерфейс, потому что они извлекают и нормализуют финансовые данные от таких поставщиков, как Reuters и Bloomberg.

Эти плагины должны быть обнаружены и управляться компонентом «Менеджер плагинов» в ядре ejb ядра. Плагины должны поддерживать загрузку, загрузку и замену во время выполнения.

В идеале интерфейсы плагина находятся в отдельном пакете, так что кто-то другой может разработать против них без необходимости моего приложения или Glassfish и даже без стека Java EE. Я также хочу развернуть плагины по требованию, а не всегда все приложение.

В настоящее время я пытаюсь использовать итератор экземпляра CDI, который отлично работает с двумя реализациями импортных сервисов, если они находятся в ядре ejb. Если я поместил одну реализацию в отдельную банку ejb, то она просто не найдена CDI. Я думаю, проблема в том, что Glassfish загружает каждый ejb jar в качестве приложения в отдельный загрузчик классов.

Теперь наступает мой текущий упрощенный код!

плагин интерфейс в отдельном банке пакет:

package com.photon.extensions; 

import java.io.Serializable; 

public interface ImportServiceExtension extends Serializable { 
    String getImportServiceName(); 
} 

Реализация плагина в отдельном пакете EJB банку, который не найден:

package com.photon.services.extensions.vitrex.services; 

import com.photon.extensions.ImportServiceExtension; 
import javax.ejb.Remote; 
import javax.ejb.Stateless; 

@Remote(ImportServiceExtension.class) 
@Stateless 
public class ReutersImportService implements ImportServiceExtension { 
    @Override 
    public String getImportServiceName() { 
     return "Reuters"; 
    } 
} 

Реализация плагин в основной EJB баночке пакет, который находится:

package com.photon.services.extensions; 

import com.photon.extensions.ImportServiceExtension; 
import javax.ejb.Stateless; 

@Stateless 
public class BloombergImportService implements ImportServiceExtension { 
    @Override 
    public String getImportServiceName() { 
     return "Bloomberg"; 
    } 
} 

Пульт дистанционного управления лицо для «Plugin Manager» в удаленных интерфейсов баночке:

package com.photon.services.extensions; 

import java.util.List; 
import javax.ejb.Remote; 

@Remote 
public interface ImportServiceExtensionsRemote { 
    List<String> getImportServiceNames(); 
} 

Реализация боб «Менеджер плагинов» в ядро ​​EJB баночке:

package com.photon.services.extensions; 

import com.photon.extensions.ImportServiceExtension; 
import java.util.ArrayList; 
import java.util.Iterator; 
import java.util.List; 
import javax.ejb.Stateless; 
import javax.enterprise.inject.Instance; 
import javax.inject.Inject; 

@Stateless 
public class ImportersService implements ImportServiceExtensionsRemote { 

    @Inject private Instance<ImportServiceExtension> importServiceExtensions; 

    @Override 
    public List<String> getImportServiceNames() { 
     Iterator<ImportServiceExtension> iter = importServiceExtensions.iterator(); 
     List<String> names = new ArrayList<>(); 
     while (iter.hasNext()) { 
      ImportServiceExtension extension = iter.next(); 
      names.add(extension.getImportServiceName()); 
     } 
     return names; 
    } 
} 

И, наконец, контроллер, который делает имена к сайт в войнах:

package com.photon.website; 

import com.photon.services.extensions.ImportServiceExtensionsRemote; 
import javax.ejb.EJB; 
import javax.enterprise.context.RequestScoped; 
import javax.inject.Named; 

@RequestScoped 
@Named 
public class ImportController implements Serializable { 

    @EJB private ImportServiceExtensionsRemote importServiceExtensions; 

    public String getImportServiceNames() { 
     String names = ""; 
     for (String name : importServiceExtensions.getImportServiceNames()) { 
      names += name; 
     } 
     return names; 
    } 
} 

В конце отображается только «Bloomberg».

Теперь мои вопросы:

  1. я на правильном пути?

  2. Если да, то что мне не хватает в коде?

  3. Есть ли лучшие решения этой проблемы (OSGI, custom clazz.forName, ...)?

ответ

1

Я не могу дать вам полный ответ, но вот некоторая пища для размышлений ...

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

Вы пригвоздили его. К сожалению, это за спецификацию JEE, поэтому ожидается его поведение.

Я не знаю о Glassfish, но может быть какая-то особенность, позволяющая делиться загрузчиком классов между развертываниями (в Wildfly называется выделение изоляции). Это может решить вашу проблему.

Другое, что я знаю из Wildfly, это то, что вы можете использовать какое-то приложение в качестве серверного модуля, который затем получит доступ ко всем другим развертываниям (и их загрузчикам классов). Если в Glassfish есть что-то подобное, вы можете попробовать это. В случае, если вы готовы дать выстрел Wildfly, here - это ссылка на вопрос, где это обсуждалось.

Теперь с КДИ точки зрения такого поведения тоже правильно, и я боюсь, что нет никакого способа, вы можете изменить его, потому что вы не имеете доступа к загрузчику класса от других внедрений (если у вас , вы можете загрузить BeanManager для данного развертывания и выполнить поиск по соответствующему компоненту).

Надеюсь, это даст вам хотя бы некоторое представление.

+0

Хорошо, спасибо! Я посмотрю на этот WildFly. – IUnknown

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