2013-06-03 21 views
9

Mając doświadczenie z wiosennym DI applicationContext.xml sposobem zadeklarowania Dependency Injection Próbuję teraz dowiedzieć się, jak zrobić to samo z Java CDE EE6.Wiele profili konfiguracji CDI (devel, beta, qa, produkcja) w jednej wojnie?

ze sprężyną, mogę wysłać mój .jar z kilku profili konfiguracyjnych jak unittest.xml, devel.xml, qa.xml, production.xml i aktywuj je za pomocą parametrów wiersza poleceń lub zmiennych środowiskowych.

z CDI, mogę używać @Alternative w beans.xml i właściwości z web.xml ale nie wydaje żadnego sposobu wysyłki wielokrotnego beans.xml dla różnych środowisk.

Nie chcę używać profili/filtrów Mavela do produkcji 4-6 wersji mojej aplikacji, chociaż rozumiem, że dla niektórych scenariuszy byłoby to lepsze rozwiązanie (np. Wysyłka gotowych wojen budujących dla klientów - ale ja używam tylko moje wojny wewnętrznie, więc oszczędźmy czas kompilacji!)

Najlepiej byłoby również móc załadować te pliki konfiguracyjne z systemu plików, aby mogły być edytowane przez sysadmins bez konieczności ponownego budowania aplikacji.

Jaki jest sposób Java EE6 posiadania wielu zestawów konfiguracji zależności i właściwości?

Jeśli nie ma żadnych, jakie są zalecane alternatywy na rok 2013? Korzystasz ze sprężyny? Szew? Guice? Widziałem wzmianki o Apache DeltaSpike, ale wciąż wyglądają na alfa ze strony internetowej.

+0

Proponuję nie dawać sysadminom możliwości zmiany wszystkiego. Pozwól im zmienić wybrany podzbiór. OK. Ale nie wszystko, a może kiedyś spędzisz długi czas debugując błąd, który popełnili, którego nie możesz odtworzyć. –

Odpowiedz

7

użyję dynamiczny producent, stosując Qualifier zidentyfikować żądany środowisku

// The qualifier for the production/qa/unit test 
@Qualifier 
@Retention(RetentionPolicy.RUNTIME) 
@Target({ElementType.TYPE, ElementType.METHOD, 
ElementType.FIELD, ElementType.PARAMETER}) 
public @interface Stage { 
    String value() default "production"; 
} 

// The interface for the stage-dependant service 
public interface Greeting{ 
    public String sayHello(); 
} 

// The production service 
@Stage("production") 
public class ProductionGreeting implements Greeting{ 
    public String sayHello(){return "Hello customer"; } 
} 

// The QA service 
@Stage("qa") 
public class QAGreeting implements Greeting{ 
    public String sayHello(){return "Hello tester"; } 
} 

// The common code wich uses the service 
@Stateless 
public class Salutation{ 
    @Inject Greeting greeting; 
    public String sayHello(){ return greeting.sayHello(); }; 
} 

// The dynamic producer 
public class GreetingFactory{ 
    @Inject 
    @Any 
    Instance<Greeting> greetings;   

    public String getEnvironment(){ 
     return System.getProperty("deployenv"); 
    } 

    @Produces 
    public Greeting getGreeting(){ 
     Instance<Greeting> found=greetings.select(
      new StageQualifier(getEnvironment())); 
     if (!found.isUnsatisfied() && !found.isAmbiguous()){ 
      return found.get(); 
     } 
     throw new RuntimeException("Error ..."); 
    } 

    public static class StageQualifier 
     extends AnnotationLiteral<Stage> 
     implements Stage { 
     private String value; 

     public StageQualifier(String value){ 
      this.value=value; 
     } 
     public String value() { return value; } 
    } 

} 

Więc tutaj pojemnik wstrzykuje wszystkie dostępne Greeting implementacje język GreetingFactory, co z kolei służy jako @Producer o zamierzonym jeden, opierając decyzję na właściwości systemu "deployenv".

+0

Dzięki za przykładowy kod źródłowy. To interesujący przykład dla @Produces, wydaje mi się, że musiałbym napisać Factory dla każdej klasy, która istnieje w wielu odmianach i może być kilka. Byłoby niechlujnie, gdybym miał kilkadziesiąt zmiennych "@Inject String password", ponieważ musiałbym użyć kwalifikatorów do rozróżnienia kilku typów String. Więc nie wydaje się skalować dla dużych aplikacji, lub? – lathspell

+0

Cóż, to cena za bezpieczeństwo typu ...Poza tym kwalifikator '@ Stage' może być użyty dla wszystkich twoich konfigurowalnych typów, to samo można powiedzieć o' GreetingFactory', który może wytworzyć wszystkie dynamicznie wstrzykiwane ziarna. Jeśli chodzi o hasło "@Inject String", możesz wprowadzić jeden kwalifikator, definiując właściwość origin tak, jak w '@Inject @Config (" db.password ") String password'. Innym (bardziej drastycznym) podejściem może być wykorzystanie przenośnego API rozszerzenia. –

+0

Jak przełączać się między etapami w kodzie? Innymi słowy, gdzie jest scena zdefiniowana/skonfigurowana i jaki plik maven musi zostać zmieniony? –

2

Powyższa odpowiedź Carlo jest dobra, mamy to wszystko w DeltaSpike with the ProjectStage. Warto przyjrzeć się, więc nie musisz sam tego pisać.

+0

Metoda _ @ Exclude (exceptIf = Development.class) @Alternative_ wyglądała obiecująco, ale często różne etapy projektu używają tej samej klasy, ale z różnymi właściwościami (nazwa użytkownika/hasła), w jaki sposób zostaną one wstrzyknięte? Dokumentacja mówi tylko "TODO" :) Chcę tego w jakimś zewnętrznym edytowalnym pliku .properties lub .xml, a nie jako publicznych plików końcowych w skompilowanej klasie Java. Jak pisałeś "my": czy powinienem otworzyć bilet Jira z listą życzeń? :) – lathspell

+0

Z pewnością zapraszam do otwarcia biletu JIRA, zapisz się na naszą [listę użytkowników] [mailto: [email protected]] lub odwiedź nas w IRC#deltaspike. To, czego szukasz, to element konfiguracji, możesz to znaleźć w tej samej dokumentacji, którą wcześniej dołączyłem. – LightGuard

1

Alternatywnym rozwiązaniem jest sugerowane przez M.-Leander Reimer w swojej prezentacji Migrating a JSF-Based Web Application from Spring 3 to Java EE 7 and CDI (zjeżdżalnia 32), używając rozszerzenia CDI:

@Alternative 
@Stereotype 
@Target({ElementType.TYPE, ElementType.METHOD}) 
@Retention(RetentionPolicy.RUNTIME) 
public @interface ProfileAlternative { 
    Profile[] value(); 
} 

public void processAnnotated(@Observes ProcessAnnotatedType<?> event) { 
    ProfileAlternative pa = getProfileAlternative(event); 
    if (profileAlternativeIsNotActive(pa)) { 
     event.veto(); 
    } 
} 

on używa niestandardowego adnotacji @ProfileAlternative naśladujący sprężyny @Profile i rozszerzenie CDI obserwując zdarzenie typu, jeśli ma przypisany profil, a profil nie jest aktywny.