2015-11-16 5 views
2

Из потока с запросом, CompletableFuture s должен быть заполнен задачей, выполняемой в исполнителе. Предоставляемый Поставщик использует услугу MessageService, относящуюся к домену, которая относится к сеансу. Эта услуга вводится Гисом.Выделение Guice OutOfScopeException при выполнении CompletableFuture

public class MessageProcessingPage { 
    private MessageService messageService; 

    @Inject 
    public MessagProcessingPage (MessageService messageService) { 
     this.messageService = messageService; 
    } 

    // Called by request scoped thread. 
    public void onProcessMessagesButton() { 
     ExecutorService executorService = Executors.newFixedThreadPool(3); 
     CompletableFuture.supplyAsync(
     // Called from a thread from the threadpool. 
     () -> {return messageService.retrieveMessageMetadataSet(x, y);} 
     , executorService); 

     ... 

    } 

    ... 
} 

MessageService имеет (сеанс Scoped) MessageRestClient, которая впрыскивается.

@SessionScoped 
public class MessageService { 
    private MessageRestClient messageRestClient; 

    @Inject 
    public MessageRestClient (MessageRestClient messageRestClient) { 
     this.messageRestClient = messageRestClient; 
    } 

    public MessageMetaDataSet retrieveMessageMetadataSet(x, y) { 
     List<MessageMetaData> listOfMetaData = messageRestClient.retrieve(x, y, z); 
     ... 
    } 

    ... 
} 

@SessionScoped 
public class MessageRestClient { 
    ... 
} 

Guice получает в беду, когда он пытается привнести MessageRestClient.

java.util.concurrent.CompletionException: com.google.inject.ProvisionException: Unable to provision, see the following errors: 

1) Error in custom provider, com.google.inject.OutOfScopeException: Cannot access scoped [MessageRestClient]. Either we are not currently inside an HTTP Servlet request, or you may have forgotten to apply com.google.inject.servlet.GuiceFilter as a servlet filter for this request. 

Я читал о методе в ServletScopes: public static <T> Callable<T> transferRequest(Callable<T> callable) Но я не вижу способ использовать это, так как нет не вызываемых объектов приходят в игру. Можете ли вы помочь мне с решением?

ответ

3

При обработке запроса сервлета в Guice, то GuiceFilter позаботилась установки надлежащего контекста (через ThreadLocal), так что он может знать, запрашивающих вы и, следовательно, применять осциллографы правильно. Экземпляры классов, аннотированные SessionScope, фактически представляют собой прокси, которые могут получить доступ к этой информации о запросе и сеансе из Guice и действовать соответствующим образом.

Задача, которую вы отправили на адрес CompletableFuture, запускается в отдельном потоке из Guice. Существует нет ThreadLocal, где Guice может получить эту информацию, и, следовательно, нет Request или Session информация, что означает, нет [SessionScope. Поскольку прокси-сервер не может ничего знать о сеансе, он выдает ошибку, которую вы получаете.

Метод ServletScopes.transferRequest должен вводить необходимую информацию, чтобы области действия работали. Должно работать, как это (но никогда не пробовали):

Callable<MessageMetaDataSet> c = ServletScopes.transferRequest(
       () -> messageService.retrieveMessageMetadataSet(x, y)); 

    CompletableFuture.supplyAsync(
    () -> c.call() 
    , executorService); 
+1

На самом деле стоит ли новый поток, но из-за нехватки времени: я заметил, что в таком сценарии следует избегать использования вспомогательной инъекции. В «MessageService» я ввел «MessageFactory» (используя вспомогательную инъекцию), который используется методом, вызываемым из задачи. Гуис тоже попал в неприятности. Поскольку я сменил вспомогательную инжектированную фабрику на обычную фабрику, все работает нормально. –

0

Попробуйте рано: Guice @Inject работает все отлично:



    import java.util.concurrent.CompletableFuture; 

    public class AsyncFire { 

     public static > void execAsync(Class asyncClass) { 
      T asyncInstance = AsyncInjector.getInjector().getInstance(asyncClass); //magic 
      CompletableFuture completableFuture = CompletableFuture.supplyAsync(asyncInstance); //business logic 
      completableFuture.exceptionally(asyncInstance); //if error 
      completableFuture.thenAccept(asyncInstance); //if success 
     } 

    } 



    public class ExampleAsync extends Async { 

     @Inject //it works 
     private EntityManager entityManager; 

     @Inject //it works 
     private DAO dao; //your 

    } 



    import java.util.function.Consumer; 
    import java.util.function.Function; 
    import java.util.function.Supplier; 

    public abstract class Async implements Supplier, Consumer, Function { 
     //... 
    } 



    import com.google.inject.Guice; 
    import com.google.inject.Injector; 
    import com.google.inject.persist.PersistService; 

    public final class AsyncInjector { 

     private static Injector injector = null; 

     public static Injector getInjector() { 
      if (injector == null) { 
       synchronized (AsyncInjector.class) { 
        if (injector == null) { 
         injector = Guice.createInjector(new MyGuiceModule()); //your guice module 
         PersistService service = injector.getInstance(PersistService.class); 
         service.start(); 
        } 
       } 
      } 
      return injector; 
     } 

    } 

Надеется, что это помогает кто-то!

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