CXF JAXRS - Comment passer la Date comme QueryParam

j'ai un service défini comme suit.

public String getData(@QueryParam("date") Date date)

j'essaie de lui passer un java.util.Date de la part de mon client (qui est jaxrs:client de CXF, pas un client HTTP générique ou un navigateur).

mon service reçoit la date comme Thu Mar 01 22:33:10 IST 2012 dans L'URL HTTP. Puisque CXF ne sera pas capable de créer un objet Date en utilisant cette chaîne, mon client reçoit une erreur 404. J'ai essayé d'utiliser un ParameterHandler côté service, mais Je ne peux toujours pas analyser avec succès parce que je ne m'attends pas à la date dans un format spécifique.

comme dans ce post , en passant par un Date est supposé fonctionner à partir de la boîte, mais je ne semble pas pouvoir obtenir le cas de base fonctionne. Dois-je faire quoi que ce soit pour transmettre avec succès un objet Date de mon client au service? Reconnaissant de toute aide.

Merci

40
demandé sur Community 2012-03-01 21:10:38

4 réponses

le problème est que JAX-RS impose que le dégroupage des paramètres se fasse de deux façons:

  1. le paramètre bean a un constructeur public qui accepte une chaîne de caractères
  2. le paramètre bean a une méthode statique valueOf(String) .

dans votre cas, la Date est dégroupée via son constructeur Date(String) , qui ne peut pas gérer le format d'entrée que votre client envoie. Vous avez deux options disponible pour y remédier:


Option 1

demandez à votre client de changer le format de la date avant de l'envoyer. C'est l'idéal, mais probablement le plus difficile à accomplir!


Option 2

gérer le format date folle. Les options pour ce sont:

modifiez votre méthode de signature pour accepter une chaîne de caractères. Essayez de construire un objet Date à partir de cela et si cela échoue, utilisez votre propre classe SimpleDateFormat personnalisée pour le parser.

static final DateFormat CRAZY_FORMAT = new SimpleDateFormat("");

public String getData(@QueryParam("date") String dateString) {
    final Date date;
    try {
        date = new Date(dateString); // yes, I know this is a deprecated method
    } catch(Exception e) {
        date = CRAZY_FORMAT.parse(dateString);
    }
}

Définissez votre propre classe de paramètres qui fait la logique mentionnée ci-dessus. Donnez-lui un constructeur de chaîne ou la méthode statique valueOf(String) qui invoque la logique. Et un autre méthode pour obtenir la Date quand tout est dit et fait.

public class DateParameter implements Serializable {
    public static DateParameter valueOf(String dateString) {
        try {
            date = new Date(dateString); // yes, I know this is a deprecated method
        } catch(Exception e) {
            date = CRAZY_FORMAT.parse(dateString);
        }
    }

    private Date date;
    // Constructor, Getters, Setters
}

public String getData(@QueryParam("date") DateParameter dateParam) {
    final Date date = dateParam.getDate();
}

enfin, vous pouvez enregistrer un gestionnaire de paramètres pour les dates. D'où sa logique est tout simplement la même chose pour les autres options ci-dessus. Notez que vous devez utiliser au moins CXF 2.5.3 Pour que votre gestionnaire de paramètres soit évalué avant qu'il ne tente la logique de dégroupage par défaut.

public class DateHandler implements ParameterHandler<Date> {
    public Map fromString(String s) {
        final Date date;
        try {
            date = new Date(dateString); // yes, I know this is a deprecated method
        } catch(Exception e) {
            date = CRAZY_FORMAT.parse(dateString);
        }
    }
}
54
répondu Perception 2012-03-01 19:26:32

Percepiton la réponse de a été très utile, mais ParameterHandler a été abandonné dans Apache cxf 3.0, consultez le Apache cxf 3.0 Guide de Migration :

CXF JAX-RS ParameterHandler a été abandonné, s'il vous plaît utiliser JAX-RS 2.0 ParamConverterProvider.

donc j'ajoute un exemple avec le ParamConverterProvider :

public class DateParameterConverterProvider implements ParamConverterProvider {

    @Override
    public <T> ParamConverter<T> getConverter(Class<T> type, Type type1, Annotation[] antns) {
        if (Date.class.equals(type)) {
            @SuppressWarnings("unchecked")
            ParamConverter<T> paramConverter = (ParamConverter<T>) new DateParameterConverter();
            return paramConverter;
        }
        return null;
    }

}

public class DateParameterConverter implements ParamConverter<Date> {

    public static final String format = "yyyy-MM-dd"; // set the format to whatever you need

    @Override
    public Date fromString(String string) {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(format);
        try {
            return simpleDateFormat.parse(string);
        } catch (ParseException ex) {
            throw new WebApplicationException(ex);
        }
    }

    @Override
    public String toString(Date t) {
        return new SimpleDateFormat(format).format(t);
    }

}

le @SuppressWarnings est requis supprimer un avertissement" opérations non contrôlées ou dangereuses " lors de la compilation. Pour plus de détails, voir .

le ParamConverterProvider peut être enregistré comme fournisseur. Voici comment je l'ai fait:

  <jaxrs:server id="myService" address="/rest">
      <jaxrs:serviceBeans>
           ...
      </jaxrs:serviceBeans>

      <jaxrs:providers>
          <ref bean="dateParameterConverterProvider" />
      </jaxrs:providers>
  </jaxrs:server>

  <bean id="dateParameterConverterProvider" class="myPackage.DateParameterConverterProvider"/>

Voir Apache cxf JAX-RS : Configuration des Services pour plus d'informations.

10
répondu Christophe Weis 2017-05-23 11:47:08

L'utilisation d'une classe DateParam personnalisée semble l'option la plus sûre. Vous pouvez alors baser vos signatures de méthode sur cela et implémenter la logique de conversion moche à l'intérieur de la méthode valueOf() ou du constructeur de classe. Il est aussi plus auto-documentant que l'utilisation de chaînes simples

1
répondu Cristian Botiza 2014-02-20 12:32:48

comme @Perception suggère dans l'option deux, vous pouvez gérer la date. Mais vous devez utiliser ce qui suit:

private Date getDateFromString(String dateString) {
    try {
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
        Date date = df.parse(dateString);
        return date;
    } catch (ParseException e) {
        //WebApplicationException ...("Date format should be yyyy-MM-dd'T'HH:mm:ss", Status.BAD_REQUEST);
    }
}

vous l'appelez de l'intérieur de la ressource comme

Date date = getDateFromString(dateString);//dateString is query param.
0
répondu kasavbere 2012-10-21 00:57:12