2017-09-04 12 views
2

Je demande Spring MVC avec les terminaux asynchrones:Comment puis-je transmettre une session http à DeferredResult?

@GetMapping 
public DeferredResult<Collection<B>> get() { 
    DeferredResult<Collection<B>> result = new DeferredResult<>(); 
    Executors.newSingleThreadExecutor().submit(() -> result.setResult(service.getB())); 
    return result; 
} 

J'essaie de sérialiser l'objet paresseux avec jackson-datatype-hibernate:

@Entity 
@Table 
public class B { 

    @Id 
    @GeneratedValue 
    private UUID id; 

    @ManyToOne(fetch = FetchType.LAZY) 
    @JoinColumn(name = "a_id") 
    private A a; 

    public A getA() { 
     return a; 
    } 
} 

Mais je reçois:

Failed to write HTTP message: org.springframework.http.converter.HttpMessageNotWritableException: Could not write JSON: could not initialize proxy - no Session; nested exception is com.fasterxml.jackson.databind.JsonMappingException: could not initialize proxy - no Session (through reference chain: java.util.ArrayList[0]->com.example.demo.B["a"]) 
+0

L'erreur est liée à la 'session Hibernate' et non à la' HTTP Session'; fondamentalement, vous essayez de marhsal aussi la propriété 'A a' de la classe' B' puisque vous avez une stratégie de fetch 'Lazy', vous obtenez l'erreur –

+0

@AngeloImmediata En fait, il fonctionne avec Callable ou CompletableFuture quand je ne cherche pas à exécuter une tâche dans un nouveau thread. J'ai ajouté le bean MappingJackson2HttpMessageConverter avec ObjectMapper personnalisé en utilisant com.fasterxml.jackson.datatype.hibernate5.Hibernate5Module. –

+0

Ceci est étrange .. l'erreur est assez claire et la stratégie de récupération est toujours claire. Avez-vous vérifié que lorsque cela fonctionne tous les paramètres sont les mêmes que ceux du test qui ne fonctionne pas? –

Répondre

0

I pense que la session fait référence à une session Hibernate et non à une session HTTP.

Votre POJO (B) contient un attribut (A a) qui est mis en correspondance avec FetchType.LAZY donc quand cet attribut est lu la session Hibernate doit être ouvert et disponible pour satisfaire les paresseux fetch.

Je suppose que vous ouvrez un thread session-per-invocation et que la réponse est gérée sur un thread différent, la session Hibernate n'est pas disponible sur le thread où B est sérialisé. Vous devez passer un certain état (probablement en créant une tâche/un runner exécutable) au thread sur lequel le résultat différé est créé, vous pouvez l'étendre pour inclure la session Hibernate actuellement ouverte lorsque vous déléguez (et n'oubliez pas de fermer cette session lorsque vous avez fini avec ce fil). Ou sinon, vous pouvez:

  • Ouvrir une nouvelle session de mise en veille prolongée sur le fil sur lequel le résultat reporté est créé
  • Modifier la FetchType afin qu'il ne soit plus paresseux.