2013-06-03 20 views
9

Có kinh nghiệm với ứng dụng Spring DI applicationContext.xml cách khai báo Dependency Injection Tôi bây giờ cố gắng tìm ra cách làm tương tự với Java EE6 CDI.Nhiều cấu hình cấu hình CDI (devel, beta, qa, production) trong một cuộc chiến?

Với Spring, tôi có thể gửi .jar với một số cấu hình cấu hình như unittest.xml, devel.xml, qa.xml, production.xml và kích hoạt chúng bằng các tham số dòng lệnh hoặc biến môi trường.

Với CDI, tôi có thể sử dụng @Alternative trong beans.xml và tài sản trong các web.xml nhưng dường như không có cách nào vận chuyển nhiều beans.xml cho các môi trường khác nhau.

Tôi không muốn sử dụng tiểu sử/bộ lọc Maven để tạo ra 4-6 phiên bản ứng dụng của mình mặc dù tôi hiểu rằng đối với một số trường hợp sẽ là giải pháp tốt hơn (tức là vận chuyển chiến tranh sẵn sàng cho khách hàng - nhưng tôi chỉ sử dụng Chiến tranh của tôi trong nội bộ vì vậy hãy tiết kiệm thời gian biên dịch!)

Tốt hơn là tôi cũng có thể tải các tệp cấu hình đó từ hệ thống tệp để chúng có thể được chỉnh sửa bởi hệ thống quản trị mà không phải xây dựng lại ứng dụng.

Cách Java EE6 có nhiều bộ cấu hình phụ thuộc và thuộc tính là gì?

Nếu không có, lựa chọn thay thế được đề xuất như năm 2013 là gì? Sử dụng Spring? Đường may? Guice? Tôi đã thấy đề cập đến Apache DeltaSpike nhưng chúng vẫn có vẻ như là đánh giá alpha từ trang web.

+0

Tôi đề nghị không cho các hệ thống quản trị khả năng thay đổi mọi thứ. Cho phép họ thay đổi tập hợp con đã chọn. ĐƯỢC. Nhưng không phải tất cả mọi thứ hoặc một ngày nào đó bạn sẽ dành một thời gian dài để gỡ lỗi sai lầm mà họ đã tạo ra mà bạn không thể tái tạo. –

Trả lời

7

Tôi muốn sử dụng một nhà sản xuất năng động, sử dụng một Qualifier để xác định môi trường mong muốn

// 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; } 
    } 

} 

Vì vậy, đây container tiêm tất cả có sẵn Greeting triển khai vào GreetingFactory, mà lần lượt đóng vai trò như @Producer cho mục đích một, dựa trên quyết định về thuộc tính hệ thống 'deployenv'.

+0

Cảm ơn mã nguồn ví dụ. Đó là một ví dụ xen kẽ cho @Sản phẩm, có vẻ như tôi sẽ phải viết một Nhà máy cho mỗi lớp tồn tại trong nhiều biến thể và có thể là một vài. Nó cũng sẽ lộn xộn nếu tôi có một dozend "@Inject String mật khẩu" biến như tôi sẽ phải sử dụng vòng loại để phân biệt một số loại String. Vì vậy, nó không có vẻ để quy mô cho các ứng dụng lớn, hoặc? – lathspell

+0

Vâng, đó là mức giá phải trả để loại an toàn ...Bên cạnh đó, vòng loại '@ Stage' có thể được sử dụng cho tất cả các loại cấu hình của bạn, điều tương tự có thể được nói cho' GreetingFactory' có thể tạo ra tất cả các bean được bơm động. Đối với '@Inject String password', bạn có thể giới thiệu một vòng loại duy nhất, xác định thuộc tính origin như trong' @Inject @Config ("db.password") Mật khẩu chuỗi'. Một cách tiếp cận khác (quyết liệt hơn) có thể là tận dụng API mở rộng di động. –

+0

Làm cách nào để chuyển đổi giữa các giai đoạn trong mã của bạn? Nói cách khác, giai đoạn được xác định/cấu hình ở đâu và xây dựng maven nào cần phải thay đổi? –

2

Câu trả lời trên của Carlo là tốt, chúng tôi có tất cả điều này trong DeltaSpike with the ProjectStage. Đáng xem xét để bạn không phải tự viết tất cả.

+0

_ @ Exclude (exceptIf = Development.class) Phương pháp @Alternative_ trông đầy hứa hẹn nhưng các giai đoạn khác nhau thường sử dụng cùng một lớp nhưng với các thuộc tính khác nhau (tên người dùng/mật khẩu), chúng sẽ được tiêm như thế nào? Tài liệu chỉ nói "TODO" :) Tôi muốn điều đó trong một số loại tệp .properties hoặc .xml có thể chỉnh sửa bên ngoài và không phải là tệp công khai cuối cùng trong lớp Java được biên dịch. Khi bạn viết "chúng tôi": tôi có nên mở một vé Jira với danh sách yêu thích không? :) – lathspell

+0

Bạn chắc chắn được chào đón để mở một vé JIRA, đăng ký với [danh sách người dùng của chúng tôi] [mailto: [email protected]], hoặc ghé thăm chúng tôi trong IRC#deltaspike. Những gì bạn đang tìm kiếm sẽ có phần cấu hình, bạn có thể thấy rằng trong cùng một tài liệu tôi đã liên kết với trước đó. – LightGuard

1

Một giải pháp thay thế được đề xuất bởi M.-Leander Reimer trong bài trình bày của ông Migrating a JSF-Based Web Application from Spring 3 to Java EE 7 and CDI (Trượt 32), sử dụng một phần mở rộng 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(); 
    } 
} 

Ông sử dụng một tùy chỉnh chú thích @ProfileAlternative bắt chước Spring @Profile và một phần mở rộng CDI quan sát sự kiện ProcessAnnotatedType tới veto() loại nếu nó được chú thích với tiểu sử và tiểu sử không hoạt động.

Các vấn đề liên quan