2013-03-16 26 views
5

Tôi đã tạo dịch vụ JAX-RS trong đó tôi muốn tiêm một bean có phạm vi ứng dụng. Vấn đề là đậu không được tiêm. Làm thế nào là điều này gây ra và làm thế nào tôi có thể giải quyết nó?Không thể tiêm @ApplicationSố đậu được kiểm tra trong dịch vụ JAX-RS

dịch vụ JAX-RS:

@Path("room") 
public class RoomService { 

    @Inject 
    GameController gc; 

    public RoomService() {} 

    @Path("create") 
    @GET 
    @Produces("application/json") 
    public String create() { 
     Room r = new Room(); 
     gc.addRoom(r); // gc is null 
     return r.toJson(); 
    } 
} 

Application scoped đậu

import java.util.ArrayList; 
import javax.enterprise.context.ApplicationScoped; 
import javax.inject.Named; 
import pepuch.multuplayergameserver.entity.Game; 
import pepuch.multuplayergameserver.entity.Room; 

@Named 
@ApplicationScoped 
public class GameController { 

    private Game game; 

    public GameController() { 
     this.game = new Game(new ArrayList<Room>()); 
    } 

    public boolean addRoom(Room room) { 
     if (!game.getRooms().contains(room)) { 
      return game.getRooms().add(room); 
     } 

     return false; 
    } 

} 
+0

Mã 'GameController' của bạn không biên dịch và cũng thiếu' @ Named'. Vui lòng không viết mã chưa được kiểm tra. Copypaste mã thực và thử nghiệm để thay thế. – BalusC

+2

Tôi đã sửa nó. Lấy làm tiếc. Tôi đã thêm '@ Named' nhưng nó vẫn không hoạt động. Tôi cho rằng '@ Named' chỉ dành cho 'EL', đó là lý do tại sao tôi không thêm cái này trước đây. – pepuch

+2

Tại sao @Named? Sẽ không tạo ra bất kỳ sự khác biệt nào. –

Trả lời

5

Bạn cần phải làm cho đậu một nguồn tài nguyên được quản lý để làm cho nó đủ điều kiện để tiêm. Ở mức tối thiểu, hãy thêm @RequestScoped vào SIB JAX-RS để làm cho nó đáng giá.

Chú thích thay thế khác là @ManagedBean. Vấn đề là, Jersey sẽ không giải quyết được mục tiêu mong muốn tiêm, nếu đậu cha mẹ không phải là trong một bối cảnh quản lý

import javax.enterprise.context.RequestScoped 

@RequestScoped 
@Path("room") 
public class RoomService { 

    @Inject 
    GameController gc; 

    public RoomService() {} 

    @Path("create") 
    @GET 
    @Produces("application/json") 
    public String create() { 
     Room r = new Room(); 
     gc.addRoom(r); // gc is null 
     return r.toJson(); 
    } 
} 

EDIT: hãy chắc chắn để có một beans.xml tập tin trong thư mục WEB-INF của bạn . tập tin beans.xml của bạn sẽ giống như thế:

<beans xmlns="http://java.sun.com/xml/ns/javaee" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee  http://java.sun.com/xml/ns/javaee/beans_1_0.xsd"> 

    </beans> 

EDIT: Dựa trên this JIRA, bạn có thể thay thế @RequestScoped với @ManagedBean

+0

Bạn có thể thêm một ví dụ không? Tôi đã cố gắng thêm '@ RequestScoped' vào lớp jax-rs nhưng nó vẫn không hoạt động. – pepuch

+0

@ pepuch, xem chỉnh sửa của tôi. Ngoài ra hãy chắc chắn rằng bạn có tập tin beans.xml trong WEB-INF của bạn hoặc người nào khác CDI tiêm sẽ không xảy ra – kolossus

+0

ManagedBean có vẻ lạ? –

1

Việc xây dựng trong bối cảnh đối tượng đang hoạt động trong servlet, dịch vụ web và lời gọi EJB hoặc trong trường hợp đối tượng ngữ cảnh hội thoại, đối với các yêu cầu JSF.

Bạn có thể gặp khó khăn khi truy cập yêu cầu, phạm vi và hạt ứng dụng từ dịch vụ JAX-RS vì nó không nêu rõ sự hỗ trợ này, tuy nhiên trong trường hợp của bạn có vẻ như bạn chỉ cần một singleton chứ không phải dựa trên ngữ cảnh hạt đậu.

Giữ nó như thế này nếu bạn đang sử dụng CDI (beans.xml),

@Singleton 
public class GameController { 
    private Game game; 
    public GameController() { 
     this.game = new Game(new ArrayList<Room>()); 
    } 
.... 
} 

Nếu bạn đang sử dụng CDI với mùa xuân (không beans.xml) sau đó giữ @Named

@Named 
@Singleton 
public class GameController { 
    private Game game; 
    public GameController() { 
     this.game = new Game(new ArrayList<Room>()); 
    } 
.... 
} 

Nếu những điều trên không hiệu quả thì tôi sẽ đề nghị đánh dấu dịch vụ JAX-RS của bạn là @ManagedBean cùng với sự thay đổi ở trên vì không rõ liệu CDI có quản lý dịch vụ JAX-RS hay không.

+0

Cảm ơn. Tôi sẽ cố gắng sử dụng '@ Singleton'. Tại sao tôi đã sử dụng '@ ApplicationScoped'? Tôi mới trong JEE và tôi nghĩ rằng 'ApplicationScoped' đậu sẽ hoạt động như' Singleton'. – pepuch

+0

Vì vậy, 'Singleton' được tạo ra cho toàn bộ container jee và 'ApplicationScoped' được tạo ra chỉ dành cho ứng dụng? – pepuch

+1

Cdi tạo thùng chứa bean riêng của mình nếu beans.xml có mặt và thêm tất cả các lần tiêm bất cứ khi nào được yêu cầu bằng cách tạo các đối tượng mới trừ khi được chỉ định là singleton, sau đó nó sử dụng cùng một bản sao của đối tượng. Ứng dụng được tạo ra và loại bỏ bởi container cdi khi bối cảnh ứng dụng của ứng dụng web được tạo ra, bị phá hủy. –