2011-11-02 107 views
4

我曾嘗試通過以下鏈接 How to wire in a collaborator into a Jersey resource?Access external objects in Jersey Resource class 但我仍無法找到工作示例展示瞭如何對注入資源類去。 我沒有使用Spring或Web容器。注入澤西資源

我的資源是

package resource; 

import javax.ws.rs.FormParam; 
import javax.ws.rs.GET; 
import javax.ws.rs.POST; 
import javax.ws.rs.Path; 
import javax.ws.rs.Produces; 

@Path("/something") 
public class Resource 
{ 
    @MyResource 
    Integer foo = null; 
    private static String response = "SampleData from Resource"; 

    public Resource() 
    { 
     System.out.println("...constructor called :" + foo); 
    } 

    @Path("/that") 
    @GET 
    @Produces("text/plain") 
    public String sendResponse() 
    { 
     return response + "\n"; 
    } 
} 

我的供應商是

package resource; 

import javax.ws.rs.ext.Provider; 
import com.sun.jersey.core.spi.component.ComponentContext; 
import com.sun.jersey.core.spi.component.ComponentScope; 
import com.sun.jersey.spi.inject.Injectable; 
import com.sun.jersey.spi.inject.InjectableProvider; 

@Provider 
public class MyResourceProvider implements InjectableProvider<MyResource, Integer> 
{ 
    @Override 
    public ComponentScope getScope() 
    { 
     return ComponentScope.PerRequest; 
    } 

    @Override 
    public Injectable getInjectable(final ComponentContext arg0, final MyResource arg1, final Integer arg2) 
    { 
     return new Injectable<Object>() 
     { 
      @Override 
      public Object getValue() 
      { 
       return new Integer(99); 
      } 
     }; 
    } 
} 

我EndpointPublisher是

import java.util.HashMap; 
import java.util.Map; 
import javax.ws.rs.core.MediaType; 
import com.sun.jersey.api.client.Client; 
import com.sun.jersey.api.client.ClientResponse; 
import com.sun.jersey.api.client.WebResource; 
import com.sun.jersey.api.container.grizzly.GrizzlyWebContainerFactory; 

class EndpointPublisher 
{ 
    public static void main(final String[] args) 
    { 

     final String address = "http://localhost:8080/"; 
     final Map<String, String> config = new HashMap<String, String>(); 
     config.put("com.sun.jersey.config.property.packages", "resource"); 
     try 
     { 
      GrizzlyWebContainerFactory.create(address, config); 
      System.out.println("server started ....." + address); 
      callGet(); 
     } 
     catch (final Exception e) 
     { 
      e.printStackTrace(); 
     } 
    } 

    public static void callGet() 
    { 
     Client client = null; 
     ClientResponse response = null; 
     client = Client.create(); 
     final WebResource resource = 
       client.resource("http://localhost:8080/something"); 
     response = resource.path("that") 
       .accept(MediaType.TEXT_XML_TYPE, MediaType.APPLICATION_XML_TYPE) 
       .type(MediaType.TEXT_XML) 
       .get(ClientResponse.class); 
     System.out.println(">>>> " + response.getResponseDate()); 
    } 
} 

我的註釋是

@Retention(RetentionPolicy.RUNTIME) 
public @interface MyResource 
{} 

但是,當我執行我的EndpointPublisher我無法注入富!

回答

7

您的InjectableProvider未正確實施。第二個類型參數不應該是你要注入的字段的類型 - 而應該是上下文 - java.lang.reflect.Type類或com.sun.jersey.api.model.Parameter類。在你的情況下,你會使用Type。所以,你的InjectableProvider實現應如下所示:

package resource; 

import javax.ws.rs.ext.Provider; 
import com.sun.jersey.core.spi.component.ComponentContext; 
import com.sun.jersey.core.spi.component.ComponentScope; 
import com.sun.jersey.spi.inject.Injectable; 
import com.sun.jersey.spi.inject.InjectableProvider; 
import java.lang.reflect.Type; 

@Provider 
public class MyResourceProvider implements InjectableProvider<MyResource, Type> { 

    @Override 
    public ComponentScope getScope() { 
     return ComponentScope.PerRequest; 
    } 

    @Override 
    public Injectable getInjectable(final ComponentContext arg0, final MyResource arg1, final Type arg2) { 
     if (Integer.class.equals(arg2)) { 
      return new Injectable<Integer>() { 

       @Override 
       public Integer getValue() { 
        return new Integer(99); 
       } 
      }; 
     } else { 
      return null; 
     } 
    } 
} 

沒有爲每個請求注射提供商(PerRequestTypeInjectableProvider)以及單注射提供商(SingletonTypeInjectableProvider)一個輔助類,這樣你就可以通過繼承進一步簡化它即:

package resource; 

import javax.ws.rs.ext.Provider; 
import com.sun.jersey.core.spi.component.ComponentContext; 
import com.sun.jersey.spi.inject.Injectable; 
import com.sun.jersey.spi.inject.PerRequestTypeInjectableProvider; 

@Provider 
public class MyResourceProvider extends PerRequestTypeInjectableProvider<MyResource, Integer> { 
    public MyResourceProvider() { 
     super(Integer.class); 
    } 

    @Override 
    public Injectable<Integer> getInjectable(ComponentContext ic, MyResource a) { 
     return new Injectable<Integer>() { 
      @Override 
      public Integer getValue() { 
       return new Integer(99); 
      } 
     }; 
    } 
} 

注意,這些助手類第2類參數是字段的類型。

還有一兩件事 - 注射發生後調用構造函數,所以你的資源的構造函數仍然會打印出...constructor called :null,但如果你改變你的資源方法返回富,你會看到你的反應我會得到99.

+0

謝謝馬丁。我意識到我的錯誤。 –

2

這個解決方案效果很好,我想分享一下我發現在球衣資源上啓用CDI。

這是有史以來最簡單的bean:

package fr.test; 

import javax.annotation.PostConstruct; 
import javax.enterprise.context.RequestScoped; 

@RequestScoped 
public class Test { 

    private int i; 

    @PostConstruct 
    public void create() { 
     i = 6; 
    } 

    public int getI() { 
     return i; 
    } 
} 

在你的資源類,我們只是注入這個bean,因爲我們在任何正常情況下這樣做:

package fr.test; 

import javax.inject.Inject; 
import javax.ws.rs.GET; 
import javax.ws.rs.Path; 
import javax.ws.rs.Produces; 

@Path("/login") 
public class LoginApi { 

    @Inject 
    private Test test; 

    @GET 
    @Produces("text/plain") 
    public String getIt() { 
     return "Hi there!" + test; 
    } 
} 

這裏是鍵。我們定義了一個新澤西州「InjectionProvider」將負責豆決議:

package fr.test; 

import javax.inject.Inject; 

import java.lang.reflect.Type; 
import javax.ws.rs.ext.Provider; 

import com.sun.jersey.core.spi.component.ComponentContext; 
import com.sun.jersey.core.spi.component.ComponentScope; 
import com.sun.jersey.spi.inject.Injectable; 
import com.sun.jersey.spi.inject.InjectableProvider; 

import fr.xxxxxxxxxx.ApplicationBeans; 

@Provider 
public class InjectionProvider implements InjectableProvider<Inject, Type> { 

    public ComponentScope getScope() { 
     // CDI will handle scopes for us 
     return ComponentScope.Singleton; 
    } 

    @Override 
    public Injectable<?> getInjectable(ComponentContext context, 
      Inject injectAnno, Type t) { 
     if (!(t instanceof Class)) 
      throw new RuntimeException("not injecting a class type ?"); 

     Class<?> clazz = (Class<?>) t; 

     final Object instance = ApplicationBeans.get(clazz); 

     return new Injectable<Object>() { 
      public Object getValue() { 
       return instance; 
      } 
     }; 
    } 
} 

InjectableProvider鍵入與實物註解我們正在處理的,和上下文類型(在這裏,普通的Java類)

ApplicationBeans只是bean解析的簡單幫助器。這裏是它的內容:

package fr.xxxxxxxxxx; 

import java.lang.annotation.Annotation; 
import java.util.Arrays; 
import java.util.Collection; 
import java.util.Set; 

import javax.enterprise.context.ApplicationScoped; 
import javax.enterprise.context.spi.CreationalContext; 
import javax.enterprise.inject.spi.Bean; 
import javax.enterprise.inject.spi.BeanManager; 
import javax.inject.Inject; 
import javax.naming.InitialContext; 
import javax.naming.NamingException; 

import fr.xxxxxxxxxxxxx.UnexpectedException; 

/** 
* Gives direct access to managed beans - Designed to be used from unmanaged code 
* 
* @author lgrignon 
* 
*/ 
@ApplicationScoped 
public class ApplicationBeans 
{ 

    protected static ApplicationBeans instance; 

    @Inject 
    private BeanManager beanManager; 

    /** 
    * Gets instance 
    * 
    * @return Instance from managed environment 
    */ 
    public static ApplicationBeans instance() 
    { 
    if (instance == null) 
    { 
     BeanManager beanManager; 
     InitialContext ctx = null; 
     try 
     { 
     ctx = new InitialContext(); 
     beanManager = (BeanManager)ctx.lookup("java:comp/BeanManager"); 
     }catch(NamingException e) 
     { 
     try 
     { 
      beanManager = (BeanManager)ctx.lookup("java:app/BeanManager"); 
     }catch(NamingException ne) 
     { 
      throw new UnexpectedException("Unable to obtain BeanManager.", ne); 
     } 
     } 

     instance = getBeanFromManager(beanManager, ApplicationBeans.class); 
    } 

    return instance; 
    } 

    /** 
    * Gets bean instance from context 
    * 
    * @param <T> 
    *   Bean's type 
    * @param beanType 
    *   Bean's type 
    * @param annotations 
    *   Bean's annotations 
    * @return Bean instance or null if no 
    */ 
    public static <T> T get(final Class<T> beanType, Annotation... annotations) 
    { 
    return instance().getBean(beanType, annotations); 
    } 

    /** 
    * Gets bean instance from context 
    * 
    * @param <T> 
    *   Bean's type 
    * @param beanType 
    *   Bean's type 
    * @param annotations 
    *   Bean's annotations 
    * @return Bean instance or null if no 
    */ 
    public <T> T getBean(final Class<T> beanType, Annotation... annotations) 
    { 
    return getBeanFromManager(beanManager, beanType, annotations); 
    } 

    @SuppressWarnings("unchecked") 
    private static <T> T getBeanFromManager(BeanManager beanManager, final Class<T> beanType, Annotation... annotations) 
    { 
    Set<Bean<?>> beans = beanManager.getBeans(beanType, annotations); 
    if (beans.size() > 1) 
    { 
     throw new UnexpectedException("Many bean declarations found for type %s (%s)", beanType.getSimpleName(), beansToString(beans)); 
    } 

    if (beans.isEmpty()) 
    { 
     throw new UnexpectedException("No bean declaration found for type %s", beanType.getSimpleName()); 
    } 

    final Bean<T> bean = (Bean<T>)beans.iterator().next(); 
    final CreationalContext<T> context = beanManager.createCreationalContext(bean); 
    return (T)beanManager.getReference(bean, beanType, context); 
    } 

    private static String beansToString(Collection<Bean<?>> beans) 
    { 
    String[] beansLabels = new String[beans.size()]; 
    int i = 0; 
    for (final Bean<?> bean : beans) 
    { 
     beansLabels[i++] = bean.getName(); 
    } 

    return Arrays.toString(beansLabels); 
    } 

} 

希望這將有助於那些想在他們的澤西島資源啓用CDI注射。

再見!