Access Play Framework route parameters during action composition - java

I have an action I want to apply to multiple routes in my Play application. These routes perform actions on a product, and a product can have various versions. I want my API to work such that the user can specify a version explicitly (via a query parameter), and if they do not specify one we will look up the latest version from the DB for them and operate on that one. So this action needs to be able to look up the latest version of a product, but we need to know which product is being asked for. In the route's controller, this is obvious. Play calls the route controller with route parameters as arguments:
#RequireProductVersion()
public CompletionStage<Result> getProduct(String productId) {
...
}
But in our action, we only have this Play internal Context object to work with. My action looks something like this:
public class RequireProductVersion extends Action<RequireProductVersion> {
#Override
public CompletionStage<Result> call(Http.Context ctx) {
final String version = ctx.request().getQueryString("version");
// if an explicit "version" parameter was specified, verify it and use it
if (version != null) {
...
} else {
// look up the latest version for this product
final String productId = ctx.request.????getParameter("productId");
return lookupLatestProductVersion(productId).thenCompose( ... );
}
}
}
Although I have some additional validity checking in that action. Sometimes I return an error from there immediately. So we could replace this action composition solution by adding the query string parameter "version" to all the routes and adding a half dozen lines of code in each of my route controllers:
#RequireProductVersion()
public CompletionStage<Result> getProduct(String productId, #Nullable String productVersion) {
final int productVersion;
try {
productVersion = Utils.getProductVersion(productId, productVersion);
} catch (ProductVersionException e) {
return CompletableFuture.completedFuture(e.getAppropriateResult());
}
...
}
But this use case is exactly what action composition should be for, I think. It just seems that the route parameters are missing. The Context object exposed in the Action call() method has a lot of stuff in it, actually. Headers are there, query parameters are there, and even the exact path being hit is there! Even if that were not so, by the point the framework has parsed the route and determined the values of the route parameters. This must be true because if it was not, then how would it know which action to call? However, it appears that these parsed parameters are completely unavailable to us. We could parse them again ourselves from the path. But why should we have to do that? We would be parsing the path twice. Why doesn't the framework expose these values?
There's an interesting article I found that, to solve a similar problem, suggests a hack that will put a url parameter into the query string parameters map.
https://alots.wordpress.com/2014/05/01/accessing-url-parameters-as-get-parameters-in-play/
However it appears to me that this method is also basically double parsing the path anyway, although I might be misinterpreting it as I'm not very familiar with Scala. If so, I might as well just hack in logic to reparse the path in my Action.

Okay so this problem is solvable in Scala. It does not appear there is currently any way to solve it in Java due to how Play Java uses annotations for action composition (and for body parsers, which is another place I ran into this exact same problem). You would have to parse the path again yourself. However, it looks like it is quite easy to accomplish in Scala. I haven’t tested either of these and I’m not very familiar with Scala, but it looks like for Play in Scala, action composition works differently.
this gist has an example of how Play Scala action composition should support this:
https://gist.github.com/wolfendale/75e8b5e9a7ace95aa7e6d123e6c6dacd
jroper’s posts in this issue thread also demonstrate what appears to me to be the same solution:
https://github.com/playframework/playframework/issues/3378#issuecomment-54925034
If those work, the technique demonstrated in the article I linked in the original post is not at all necessary to solve this problem if you are using Scala. However, because it only requires writing some code in Scala (whereas for the technique demonstrated by wolfendale and jroper, you need to write your controller in Scala as well), it could be a useful way to solve this problem and still write most of your application in Java. I don’t know for sure. I haven’t tested it and I’m not interested in that kind of hack.

You can't, at least, not out of the box. Play doesn't provide ways to get the request params in action composition.
Basically : You have to parse yourself.

Related

Use entity method as MapStruct source

Background
We are currently implementing an application using hexagonal architecture. Our REST API DTOs are mapped to our entities via MapStruct. This works fine. (Though, it would be much nicer if MapStruct would have support for hierarchical structures.)
Problem
However, we are facing a problem which is best described by the following example:
Consider you have an entity Person that stores the date of birth. Now, this
entity has a method which might be called int calculateAge().
The REST API's PersonDto will get an attribute int age.
Now, we want MapStruct to generate this mapping for us. Our approach was to try to configure #Mapping(target = "age", ...) to use the int calculateAge() method as source, but we did not succeed.
Believing this might be a straightforward application of MapStruct, we were quite disappointed to not come up with a clean solution after searching on this topic for hours.
Solutions
We found two solution approaches that work, but are (in our opinion) not really maintainable:
Use #Mapping(expression = "java(...)")
Use #AfterMapping to post process the constructed DTO and implement the required mappings in the annotated method
Question
Is there a cleaner way to achieve our goal, something which might look like this #Mapping(sourceMethod = "calculateAge", target = "age)?
Is there a cleaner way to achieve our goal, something which might look like this...
No, there isn't as of the MapStruct latest stable version (1.4.1.Final) of time of writing this answer. You have basically two choices which heavily depends what exactly and how you want to map the fields. I describe shortly in what case each solution is suitable for:
The first solution using expression introduces the problem the methods are hardcoded in the annotation. I prefer this solution only in the case of simple format conversions or calculations without calling a custom method (only from the existing Java API). Anyway, even with your proposed solution it would be still hardcoded. The syntax is the only thing that changes. There is effectively no difference in terms of maintainability:
#Mapping(target = "age", expression = "java(...)") // current API
#Mapping(sourceMethod = "calculateAge", target = "age") // hypothetical
Feel free to request for such feature. This solution in any case also requires imports within the mapper (#Mapper(imports = Another.class)) as well as the "hypothetical" one.
The annotation #AfterMapping is useful in case of more complex transformations and calculations. It's not as clean as a single annotation call and in fact you still write the mapping manually, however, it brings more control over the called methods which the IDE highlights before the compilation (at least you don't need an additional IDE-specific plugin). I'd go for this solution in case I need to call my custom methods and logics.
From what I've seen, Mapstruct relies on standard getters and setters. If you want to use a specific method then Mapstruct does work with #qualifiers, but I don't think the method can be in the entity. From my experience the best solution is to use #AfterMapping, as you mentioned.

Java Android: How to use Predicate<T> and Room together to retrieve specific elements from a database?

I'm coming from a C# background and trying to implement an Android App. In .Net C#, retrieving specific data from a database is relatively easy using Entity Framework and Linq, my usual approach is something like this (simplified for clarity):
public IQueryable<T> GetElements<T>()
where T : class, IDBKeyProvider
{
return this.db.Set<T>().Where(e => e.Dbstate == (int)DBState.Active);
}
This method call results in a generic IQueryable and later on, I can use the power of deferred execution and expression trees to specify exactly which elements I want using a predicate, loading only desired elements in memory.
This is something I would very much like to go for in my Android App, however, I'm not exactly sure how I could arrive at a similar result, if I can at all.
I looked into some Java Predicate examples, which seemed promising and I also found Room to be delightfully familiar. My problem, however, is that I cannot make my queries fully customizable due to the fact that, Room still needs some hard-coded info about my db (original here):
#Dao
public interface MyDao {
#Query("SELECT first_name, last_name FROM user WHERE region IN (:regions)")
public LiveData<List<User>> loadUsersFromRegionsSync(List<String> regions);
}
I could perhaps extract the relevant pieces of information with Java Reflection from the predicate parameter, but I feel this to be a hack rather than a proper solution.

Design for executing a "pipeline" of user-defined actions based on input

Scenario
A web service receives a request in the form of XML from some other system, based on the contents of this request the web service should perform an arbitrary number of user-definable tasks (such as storing the contents of the XML to a database, extracting certain values, making a call to some other service etc). The behaviour of the requesting system cannot be changed (e.g. to call different actions for different things).
Proposed Design
My proposed design would be to have an interface something like...
interface PipelineTask {
public void Run(String xml);
}
With implementations of this for each user action, for example...
public class LogToDatabaseTask implements PipelineTask {
public void Run(String xml) {
db.store(xml); // some call to database to store.
}
}
Then a database table containing rules (maybe as XPath expressions), and the class to invoke should those rules be satisfied by the received document. I'd then use reflection - or perhaps a factory(?) - to invoke the correct implementation and run it.
Question
To me, it sounds like there should be some kind of existing pattern to implement something like this which I've missed and can't find online anywhere. Would this kind of approach make sense - or is there some better, perhaps more flexible way of doing this?
As you already mentioned, a rule seems a good fit for this case. You can define a rule that takes facts related to the current state and provide the next action in the sequence. Below is a simple java rule method as example. You can also use a rules framework like drools. The response from the rule can be used with a factory or a strategy:
For example, consider the sequence of actions:
UPDATE_DB
EXTRACT_VALUES
INVOKE_XYZ_SERVICE
END
For every web service request check the rule after every step and execute actions until you receive a rule response with next action END. The rulerequest also contains the contents of input document:
public RuleResponse execute(RuleRequest request) {
//initialization and extraction code here
if(request.previousAction.equals("EXTRACT_VALUES") && ....) {
RuleResponse.nextAction = "INVOKE_XYZ_SERVICE".
}
return response;
}
I know that you tagged the question as Java, but actually you can reuse a lot of the MSDN logical model of the Pipes & filters design pattern. The article is very good and I've used already in Java modules.
First you can also read this about Pipeline_software - it helped me a lot with ideas.

Dynamic Fields and/or Artificial Methods

I work with a dynamic Dataset model, which (in short) takes in attributes and stores them in a Map like this...
Dataset dataset = new Dataset();
dataset.setAttribute("name", "value");
...for later recovery, like this...
String value = dataset.getAttribute("name");
...and that has worked wonderfully for my purposes. But now I'm in a place where I'd like to use a templating engine to dynamically generate HTML. In the template, it's not ideal for me to do a lot of ${dataset.getAttribute("name")}. It would be rather nice if I could create artificial methods whenever something was added to a Dataset. For instance, if I did this...
dataset.setAttribute("name", "value");
...I'd like to be able to retrieve it like this...
String name;
name = dataset.name;
//or
name = dataset.getName();
...but so far I haven't been able to pull it off. What approach might I take here? Is it even doable?
Edit:
I understand that Velocity offers Property Lookup Rules to try to resolve dataset.name to dataset.get("name"), and that's great, but I need to know how to achieve this in the case that Velocity isn't the target as well.
See http://velocity.apache.org/engine/releases/velocity-1.5/user-guide.html#propertylookuprules
If your method was named get(String attribute) rather than getAttribute(String attribute), you could use the same syntax as for regular properties. So, either refactor your class, or add an additional get method that does the same thing as getAttribute, or transform your object into a Map, which has a get method.
In the past I have generated POJOs dynamically with Objectweb's ASM. This has the benefit that the underlying fields are type safe and much more efficient (esp for privative values)
You can use Dynamic Spring proxies with AOP technology or CGLib proxies. AOP could be used to describe getters like this : execution(public * com.bla.YourClass.get*())")
From what I've seen, it's fairly common for template engines for Java to support both
getters/setters of the form getAttribute, and
implementation of the Map interface
Before you spend too much time looking for a more generic solution (assuming the above won't be supported like it is in Velocity), it's probably worth taking a look at the other engines to see if any of them don't support it. If all your possible targets do, then you're probably fine relying on it.
I'm a big fan of making sure you actually have a problem before you spend the time to solve it.

Exception when serializing a stateless object with jackson Json

I have been using the jackson implementation of the json protocol in my own little project, and it has gone just fine a while now until I decided (for the first time) to serialize a stateless object.
I know that might sound weird, why would I want to send a stateless object? What I serialize is requests for a server, and this particular one conatins no fields, just code for an instruction on the server side. My model can take any ClientRequest implementation and call it's perform() method. I want it to work even though the request comes without fields.
Code looks like this:
public class GetWallInputsRequest implements ClientRequest<List<WallInput>>
{
#JsonCreator public GetWallInputsRequest()
{
}
#Override public ServerResponse<List<WallInput>> perform()
{
return new WallMessageResponse( Wall.WALL.getInputs() );
}
}
I get JsonMappingException: No serializer found for class GetWallInputsRequest.
Google does not help me, which makes me wonder if I'm just being stupid. Sadly I don't see a way out of this.
I solved it after a lot of brute force attempting different things. And by solved it I mean not figured it out but made it work. By adding the line:
#JsonAutoDetect(getterVisibility=JsonAutoDetect.Visibility.NONE)
above the class declaration it seems to work out. Why this is necessary I don't know, but now It sends an empty json string instead of crashing.
The documentation says
Value that indicates that no access modifiers are auto-detectable: this can be used to explicitly disable auto-detection for specified types.
Since your class doesn't include any explicit notations to tell Jackson that there's a field or method to serialize, it determines that there is indeed nothing to look for. Without this, I presume, it's going to expect something, as suggested in the documentation quoted.
http://jackson.codehaus.org/1.9.0/javadoc/org/codehaus/jackson/annotate/JsonAutoDetect.Visibility.html

Categories