2016-04-26 5 views
1

Я в настоящее время реорганизую веб-приложение в Джерси и хочу связать некоторые проблемы с перекрестными проблемами в своих классах и использовать аннотации для методов перехвата. Например, существует множество методов, когда мне нужно проверить, является ли пользователь владельцем объекта, который он хочет изменить (в моем случае это проект). Поэтому внутри перехватчика мне нужно сделать вызовы в базе данных, и, хотя соответствующие DAO, которые были введены, были бы лучшим способом.@Inject не работает в MethodInterceptor под управлением HK2

В настоящее время мой перехватчик выглядит следующим образом:

public class ProjectOwnerCheckInterceptor implements MethodInterceptor { 

     @Inject 
     private EntityManager em; 

     @Inject 
     private UserProvider userProvider; 

     @Inject 
     private RMUserDAO rmUserDAO; 

     @Inject 
     private ProjectDAO projectDAO; 

     public ProjectOwnerCheckInterceptor() { 
     // TODO Auto-generated constructor stub 
     } 

     @Override 
     public Object invoke(MethodInvocation arg0) throws Throwable { 

      // First of all let's get the annotation 
      ProjectOwnerCheck check = arg0.getMethod().getAnnotation(ProjectOwnerCheck.class); 

      // if there is no check, then just proceed! 
      if (check == null) 
       arg0.proceed(); 

      long projectId = (long) arg0.getArguments()   [check.projectIdIndex()]; 

      // Handling ownership!! 
      Project project = getProjectOrThrow(projectId); 

      return arg0.proceed(); 

     } 
    } 

Обычай аннотация прямо вперед. Мне нужно добавить какую-нибудь информацию, какой аргумент позиция EntityId в методе должен проверить это как количество параметров и типов различны:

@Retention(RetentionPolicy.RUNTIME) 
@Target({ ElementType.METHOD }) 
public @interface ProjectOwnerCheck { 

    int projectIdIndex() default -1; 

} 

Для Джерси/HK2, чтобы знать, что делать с перехватчиками я создал фильтр реализация InterceptionService:

public class HK2InterceptorFilter implements InterceptionService { 

    private final static MethodInterceptor PROJECT_CHECK_METHOD_INTERCEPTOR = new ProjectOwnerCheckInterceptor(); 
    private final static List<MethodInterceptor> PROJECT_CHECK_METHOD_LIST = Collections 
      .singletonList(PROJECT_CHECK_METHOD_INTERCEPTOR); 

    public HK2InterceptorFilter() { 
     // TODO Auto-generated constructor stub 
    } 

    @Override 
    public Filter getDescriptorFilter() { 

     return BuilderHelper.allFilter(); 

    } 

    @Override 
    public List<MethodInterceptor> getMethodInterceptors(Method method) { 

     if (method.isAnnotationPresent(ProjectOwnerCheck.class)) 
      return PROJECT_CHECK_METHOD_LIST; 

     return null; 

    } 

    @Override 
    public List<ConstructorInterceptor> getConstructorInterceptors(Constructor<?> constructor) { 
     // TODO Auto-generated method stub 
     return null; 
    } 

} 

Я связывание этого фильтра в моем JerseyApplication классе:

register(new AbstractBinder() { 
      @Override 
      protected void configure() { 
       try { 

        bind(HK2InterceptorFilter.class).to(InterceptionService.class).in(Singleton.class); 
        bind(getPasswordStorage()).to(PasswordStorage.class); 
        bind(getDocumentService()).to(DocumentService.class); 
        bind(UserManagementAccessor.getUserProvider()).to(UserProvider.class); 
       } catch (Exception e) { 
        throw new InternalServerErrorException(e); 
       } 
      } 
     }); 

Когда установить контрольную точку в моем перехватчике Я вижу, что он правильно создан и называется методом gots. Но я полностью пропустил все те поля @Inject, которые мне нужно сделать, чтобы сделать чек. Я что-то упустил или это невозможно в HK2. Раньше я работал с Guice, и там он работает (я - из-за того, что база кода приложения довольно большая, но ограничена по времени - привязана к HK2 :)).

Спасибо за вашу помощь заранее!

PS:

Я использую Джерси 2,17

ответ

1

Проблема заключается в том перехватчик никогда не проходит через жизненный цикл DI, потому что если это не сервис в контейнере. Вы создаете его сами. Когда вы делаете это в рамках DI, большую часть времени вы можете ожидать этого результата.

Что вы можете сделать может, хотя явно вводит его самостоятельно, используя контейнер HK2, ServiceLocator. Вы вводите локатор в InterceptionService, а затем вызываете locator.inject(interceptor). Этот метод является методом общего назначения, чтобы явно ввести любой произвольный объект. Таким образом, вы можете изменить это что-то вроде

private final List<MethodInterceptor> PROJECT_CHECK_METHOD_LIST; 

@Inject 
public HK2InterceptorFilter(ServiceLocator locator) { 
    final MethodIntercator i = new ProjectOwnerCheckInterceptor(); 
    locator.inject(i) 
    PROJECT_CHECK_METHOD_LIST = Collections.singletonList(i); 
} 

Другая проблема, которую вы собираетесь столкнуться в том, что перехватчик одноэлементно, но все ваши услуги вы пытаетесь привнести в вид, как они запрос область действия. Это проблема, поскольку они должны меняться в зависимости от запроса. Для этого мы можем сделать их прокси. Мы можем сделать это просто приковав метод пара в связывающем

bind(getPasswordStorage()) 
    .to(PasswordStorage.class) 
    .proxy(true) 
    .proxyForSameScope(false) 
    .in(RequestScoped.class); 

Смотрите также:Injecting Request Scoped Objects into Singleton Scoped Object with HK2 and Jersey

Ниже приведен полный пример использования Jersey Test Framework.

import java.lang.annotation.ElementType; 
import java.lang.annotation.Retention; 
import java.lang.annotation.RetentionPolicy; 
import java.lang.annotation.Target; 
import java.lang.reflect.Constructor; 
import java.lang.reflect.Method; 
import java.util.Collections; 
import java.util.List; 
import java.util.logging.Logger; 

import javax.inject.Inject; 
import javax.inject.Singleton; 
import javax.ws.rs.GET; 
import javax.ws.rs.Path; 
import javax.ws.rs.core.Context; 
import javax.ws.rs.core.HttpHeaders; 
import javax.ws.rs.core.Response; 

import org.aopalliance.intercept.ConstructorInterceptor; 
import org.aopalliance.intercept.MethodInterceptor; 
import org.aopalliance.intercept.MethodInvocation; 
import org.glassfish.hk2.api.Filter; 
import org.glassfish.hk2.api.InterceptionService; 
import org.glassfish.hk2.api.ServiceLocator; 
import org.glassfish.hk2.utilities.BuilderHelper; 
import org.glassfish.hk2.utilities.binding.AbstractBinder; 
import org.glassfish.jersey.filter.LoggingFilter; 
import org.glassfish.jersey.process.internal.RequestScoped; 
import org.glassfish.jersey.server.ResourceConfig; 
import org.glassfish.jersey.test.JerseyTest; 
import org.junit.Test; 

import static org.hamcrest.CoreMatchers.containsString; 
import static org.hamcrest.CoreMatchers.is; 
import static org.junit.Assert.assertThat; 

/** 
* Stack Overflow question http://stackoverflow.com/q/36859669/2587435 
* 
* Run this like any other JUnit test. One one required test dependency: 
* 
* <dependency> 
*  <groupId>org.glassfish.jersey.test-framework.providers</groupId> 
*  <artifactId>jersey-test-framework-provider-inmemory</artifactId> 
*  <version>${jersey2.version}</version> 
* </dependency> 
* 
* @author Paul Samsotha 
*/ 
public class InterceptionTest extends JerseyTest { 

    public static interface HeaderProvider { 
     String getXCustomHeader(); 
    } 

    public static class HeaderProviderImpl implements HeaderProvider { 
     @Context 
     private HttpHeaders headers; 

     @Override 
     public String getXCustomHeader() { 
      return headers.getHeaderString("X-Custom-Header"); 
     } 
    } 

    @Target(ElementType.METHOD) 
    @Retention(RetentionPolicy.RUNTIME) 
    public static @interface Intercept { 
    } 

    public static class MyMethodInterceptor implements MethodInterceptor { 

     @Inject 
     private HeaderProvider provider; 

     @Override 
     public Object invoke(MethodInvocation invocation) throws Throwable { 
      return provider.getClass().getName() + ":" + provider.getXCustomHeader(); 
     } 

    } 

    public static class InterceptionHandler implements InterceptionService { 

     private final List<MethodInterceptor> interceptors; 

     @Inject 
     public InterceptionHandler(ServiceLocator locator) { 
      final MethodInterceptor interceptor = new MyMethodInterceptor(); 
      locator.inject(interceptor); 
      interceptors = Collections.singletonList(interceptor); 
     } 

     @Override 
     public Filter getDescriptorFilter() { 
      return BuilderHelper.allFilter(); 
     } 

     @Override 
     public List<MethodInterceptor> getMethodInterceptors(Method method) { 
      if (method.isAnnotationPresent(Intercept.class)) { 
       return interceptors; 
      } 
      return null; 
     } 

     @Override 
     public List<ConstructorInterceptor> getConstructorInterceptors(Constructor<?> c) { 
      return null; 
     } 
    } 

    public static class Binder extends AbstractBinder { 
     @Override 
     protected void configure() { 
      bind(InterceptionHandler.class) 
        .to(InterceptionService.class) 
        .in(Singleton.class); 
      bind(HeaderProviderImpl.class) 
        .to(HeaderProvider.class) 
        .proxy(true) 
        .proxyForSameScope(false) 
        .in(RequestScoped.class); 
     } 
    } 

    @Path("intercept") 
    public static class TestResource { 

     @GET 
     @Intercept 
     public String get() { 
      return null; 
     } 
    } 

    @Override 
    public ResourceConfig configure() { 
     return new ResourceConfig(TestResource.class) 
       .register(new Binder()) 
       .register(new LoggingFilter(Logger.getAnonymousLogger(), true));   
    } 

    @Test 
    public void shouldReturnHeaderAndProxyClass() { 
     Response response = target("intercept").request() 
       .header("X-Custom-Header", "Value1") 
       .get(); 
     assertThat(response.getStatus(), is(200)); 
     String entity = response.readEntity(String.class); 
     response.close(); 
     assertThat(entity, containsString("Value1")); 
     assertThat(entity, containsString("Proxy")); 

     // Change header to make sure we aren't getting the same HttpHeaders instance 
     response = target("intercept").request() 
       .header("X-Custom-Header", "Value2") 
       .get(); 
     assertThat(response.getStatus(), is(200)); 
     entity = response.readEntity(String.class); 
     response.close(); 
     assertThat(entity, containsString("Value2")); 
     assertThat(entity, containsString("Proxy")); 
    } 
} 
+0

Это решило это! БЛАГОДАРЯ!! – Inkvine

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

  • Нет связанных вопросов^_^