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
4 réponses
le problème est que JAX-RS impose que le dégroupage des paramètres se fasse de deux façons:
- le paramètre bean a un constructeur public qui accepte une chaîne de caractères
- 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);
}
}
}
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.
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
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.