2017-08-04 4 views
0

Je souhaite utiliser la gestion des exceptions avec les clients Restlet Framework et GWT. Restlet Framework prend en charge le concept d'exceptions annotées tel que décrit dans ce message;Recevoir des exceptions personnalisées à partir de Restlet Framework dans le client GWT

http://restlet.com/company/blog/2015/12/21/exception-handling-with-restlet-framework/

Dans mon projet, j'ai créé un LocationNameException

@Status(value = 409) 
public class LocationNameException extends Exception 
{ 
    ... 

    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 
    public LocationNameException(String pMessage, Throwable pCause) 
    { 
     super(pMessage, pCause); 
    } 
} 

Et utiliser dans mon ServerResource;

@Override 
    @Transactional(rollbackOn = LocationNameException.class) 
    public LocationDto postLocation(LocationDto pLocationDto) throws LocationNameException 
    { 
     ... 

     Location lLocation = new Location(pLocationDto); 

     try 
     { 
      LocationDao lLocationDao = getLocationDao(); 
      lLocationDao.persist(lLocation); 
     } 
     catch (PersistenceException pPersistenceException) 
     { 
      throw new LocationNameException("Location requires unique Name", pPersistenceException); 
     } 

     ... 

     return lLocationDto; 
    } 

Avec l'interface

public interface LocationListServerResourceInt 
{ 
    ... 

    @Post 
    LocationDto postLocation(LocationDto pLocationDto) throws LocationNameException; 

    ... 
} 

Cela fonctionne, dans le cas d'une exception l'appel retourne le code 409;

enter image description here

Et au onFailure côté client GWT() est appelée;

private class PostLocationCallback implements AsyncCallback<LocationDto> 
{ 
    ... 

    @Override 
    public void onFailure(Throwable pCaught) 
    { 
     mCallback.onFailure(pCaught, mLocationDto); 
    } 
} 

Mais paramètre pCaught contient seulement ResourceException avec le code d'état 409. Mon LocationNameException ne figure pas dans la pile de cause sous-jacente. J'ai besoin de cette LocationNameException pour la gestion appropriée des messages d'erreur.

La raison en est la ServerResourceProxy LocationListServerResourceProxyImpl générée par le Restlet GWT ClientProxyGenerator;

public void postLocation(LocationDto param1, final LocationDto> callback) 
{  
    ... 

    public void handle(Request request, Response response) 
    { 
     if (getClientResource().getStatus().isError()) 
     {  
      callback.onFailure(new ResourceException(getClientResource().getStatus())); 
     } 
     else 
     { 

    ... 

} 

Je pense que je dois réécrire la méthode Post dans le ClientProxyGenerator;

enter image description here

Le LocationNameException est présent dans les données de réponse de sorte the Basic approach using the getResponseEntity() method of the ClientResource class should be possible.

Est-ce la voie à suivre? Ou puis-je attraper l'exception LocationNameException ailleurs comme suggéré par Catching annotated exceptions?

Il est vraiment difficile d'essayer une approche différente à cause du code généré. Existe-t-il un moyen facile de contourner le générateur de code avec des classes personnalisées?

+0

Il reste maladroitement silencieux autour de ce problème ... Restlet/GWT est-il toujours vivant? Quelqu'un at-il déjà utilisé des exceptions de serveur dans les clients GWT avec Restlet? –

+0

Salut Roland, le support pour l'exception annotée dans Restlet/GWT n'a pas été développé, mais il devrait être techniquement réalisable. Pensez-vous que vous pourriez contribuer? Content de vous soutenir pendant ce processus. –

+0

Bonjour Jérôme, oui je pense que je peux y contribuer. Le défi n'est pas l'exception annotée (je peux juste utiliser l'approche de base décrite) mais le ClientProxyGenerator (donc le truc du compilateur GWT ...). J'ai essayé d'utiliser le code source généré dans mon projet mais il y a des problèmes avec le ServerResourceProxy_TypeSerializer ... Avez-vous un exemple de travail/compilation ServerResourceProxyImpl/ServerResourceProxy_TypeSerializer avec lequel je peux jouer? –

Répondre

0

Avec l'aide de Jérôme Louvel et Thierry Boileau i a créé une nouvelle ClientProxyGenerator() qui prend en charge des exceptions personnalisées vers un client GWT;

enter image description here

Il suffit de spécifier l'exception de l'interface dans le ServerResourceProxy (ClientProxy)

enter image description here

et le tour est joué

enter image description here

enter image description here

Il est possible d'utiliser cette version personnalisée de ClientProxyGenerator() dans votre projet immédiatement.

Download custom ClientProxyGenerator

et placez-le dans un paquet sur le serveur (par exemple package com.ludus.server.util)

enter image description here

Dans le module XML GWT changer le ClientProxyGenerator à la nouvelle version sur le serveur;

enter image description here

Et vous êtes prêt à aller avec vos exceptions personnalisées, mais ce serait bien si cette extension serait intégrée dans le cadre Restlet.

0

Comme déjà mentionné l'emplacement LocationNameException est présent dans les données de réponse. Par conséquent, nous pouvons l'obtenir, tout comme une entité normale;

... 

     public void handle(Request request, Response response) 
     { 
      if (getClientResource().getStatus().isError()) 
      { 
       LocationNameException lLocationNameException = null; 
       boolean serializationError = false; 

       try 
       { 
        if (response.isEntityAvailable()) 
        { 
         if (MediaType.APPLICATION_JAVA_OBJECT_GWT.equals(response.getEntity().getMediaType())) 
         { 
          lLocationNameException = new ObjectRepresentation<LocationNameException>(
            response.getEntity().getText(), 
            (SerializationStreamFactory) MyLocationListServerResourceProxyImpl.this, false) 
            .getObject(); 
         } 
         else 
         { 
          throw new IOException("Can't parse the enclosed LocationNameException."); 
         } 
        } 
       } 
       catch (Throwable e) 
       { 
        serializationError = true; 
        callback.onFailure(new ResourceException(e)); 
       } 

       if (!serializationError) 
       { 
        callback.onFailure(lLocationNameException); 
       } 
      } 
      else 
      { 

... 

Le ClientProxyGenerator doit connaître le type d'exception (dans ce cas, LocationNameException). Par conséquent, nous spécifions l'exception dans l'interface ClientProxy;

@Post 
    void postLocation(LocationDto pLocationDto, AsyncCallback<LocationDto> pResult) throws LocationNameException; 

Et utiliser getExceptionTypes() ou getGenericExceptionTypes() dans le ClientProxyGenerator;

Class<?>[] exceptionTypes = method.getExceptionTypes(); 
    java.lang.reflect.Type[] genericExceptionTypes = method.getGenericExceptionTypes(); 

Bien sûr, toutes les méthodes REST n'utilisent pas d'exception personnalisée.Lorsque getExceptionTypes() renvoie une liste vide, nous retournons juste le bon vieux code d'état;

callback.onFailure(new ResourceException(getClientResource().getStatus()));