The functionality can be gathered into an argument extractor. Sadly, the official documentation only shows an example where the session is used to extract a simple session cookie. But what if you have to get complex form data? Ideally, one wants a clean action method signature, where the instance is injected correctly. This can be done with simply with an annotation:
public Result saveTrip(Context context, @argumentextractors.Trip Trip trip) {
It's important to note, that you can't use other built-in extractors (Param, Params) any more, after you parsed the request. Additionally, your own extractor has to be the first extracting paramter in the signature.
The marker interface specifies the extractor class:
@WithArgumentExtractor(TripExtractor.class) @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.PARAMETER}) public @interface Trip { }
The magic then has to be implemented by yourself. Therefore, extend a BodyAsExtractor
public Trip extract(Context context) {}
Your form data has to be gathered now. Took me some time to find out how to do this - actually, you can do
String body = ""; while (context.getReader().ready()) { body += context.getReader().readLine(); }
and that's it. I was'n able to use the InputStream the context provides directly. Now the ugly part. the params string of the form http://example.org/path/to/file?a=1&b=2&c=3 should result in a list of a=1, b=2, c=3. Since this is a common task, it's implemented in the apache commons htmlUtils - nice wordplay. I extracted some single methods from their library, because I only use a few ones. Now, you have to apply the parsed values by hand. To mention would be, that this can only work, if the keys you use to extract all the stuff don't change between forms. Otherwise, you would have to implement another extractor.
trip.getStops().clear(); for (int x = 2; x < params.size(); x++) { trip.getStops().add(params.get(x).getName()); } return trip;
The nice thing is now, that everyone who uses this object class, can use the extractor and afterwards just has to save the instance regularly in the controller action:
manager.merge(trip);
I'm curious if this is the intended way to extract stuff from forms. It's a pity that such an important requirement isn't documented better.
Keine Kommentare:
Kommentar veröffentlichen