Spring MVC: How to reroute to a different controller/method dynamically? - java

To explain the use case in as few words as possible, we have a set of controllers (and associated services) that we want to deprecate. In this same project we have introduced fancy new stuff to take its place. For the simplicity sake, all the same REST endpoints are implemented by both sets of work. The only difference being the first set of controllers are namespaced to /v1/ and the latter /v2/.
To verify that all this new work actually works in production, the goal was to incrementally push traffic in that direction. Whether it is "make 5% of the traffic go to the new stuff" or "for all calls dealing with orders from Factory X go to the new stuff" or some other piece of routing logic.
I'm trying not to touch the old code (that would require retesting all of it), so figured I could just hijack how Spring maps a request to a controller. Initially I thought I could I extend RequestMappingHandlerMapping and override the lookupHandlerMethod() call, but while that method is protected in the Abstract base class the very important map of handlerMethods and urlMap are private: leaving me in the lurch when it comes to providing a differing but existing handlerMethod.
I'd like to leverage as much as I can from the AbstractHandlerMethodMapping and the RequestMappingHandlerMapping classes. Currently, without access to the handler maps, I'm debating whether to completely use them, but change the lookupPath string and create my own HttpServerRequest class where I've edited the request URI to match my "new" controllers.
Any ideas? I'm hoping there is something I am missing.

Related

Spring MVC: is using forms in the service layer a good practice?

Let's say there is an application which uses the forms package and <whatever>Form.java for validation purposes in the controller layer, so every request which needs validation has a corresponding <requestName>Form.java class.
This results in controllers methods signatures looking like this:
TemplateController.java
#PostMapping
public Mono<SmsMessageTemplate> create(#Valid #RequestBody Mono<TemplateForm> templateForm)
and then there is a service layer with method signatures looking like this:
TemplateService.java
public Mono<SmsMessageTemplate> create(TemplateForm formData) {...}
It is also possible to implement it like so:
TemplateService.java
public Mono<SmsMessageTemplate> create(String template name, String templateText) {...}
Which way is better and why? I think passing the Form classes to the service layer may be mixing of the layers concept and one should keep forms in the controller layer for a better understanding of the parameters passed without a need to navigate through classes back and forth. Do I miss something?
Such decisions trully depend on various factors f.e:
- the complexity and volume of the project (is it just a small service, or a full blown CMS / ERPS etc?)
are you going to be re-using the service in other modules/projects
are you going to distribute service interface jars ?
(then you need to think about the modules and perhaps the *Form object will not even be at the controller side - you wouldn't want to distribute your controller classes to 3rd party clients)
what about a form that contains 20 fields ? you surelly wont pass 20 arguments
what about the case of a service method that does CRUD on complex entities, say a User ? you will probably have a couple of forms / validations (register, edit) and perhaps different types of users with different options so types * actions forms. (in which case you may consider a User domain object (in a domain package) and multiple controller side form objects (you will probably need to populate a User object from/to a Form).
generally speaking, as mentioned above, it's very opinion-based but in my opinion the overall complexity and envisaged size of each project will affect your final decision.

How to make a GAE server repeat operation?

If I want to update a cache every minute, or do something else every hour, where I should put my code (Java) ? As I think, not in the servlets. Can you help me with it?
You need to use cron jobs:
Scheduled Tasks With Cron for Java
This is exactly what they have been designed for.
The answer by Andrei Volgin is correct, and you need to pursue the link.
However, I want to address the 'not in the servlets' part of your questions. I think you are asking from a design perspective whether the code should reside inside the servlet class. I have answered this for myself recently.
The way Crons and Tasks are implemented by GAE, the code will be called via servlets, as these are background URL calls. So, theoretically, the code can be in the servlet class itself. If you are using a framework like Spring, you will probably have one entry point servlet and your own handlers/managers/services. In this case, you can write the code in the handler.
In my project, I created a single entry point servlet for all UI related processing. When I needed to implement the first Task Queue I created another entry point servlet for the queues/crons and then coded inside new handlers.
In general, your app design would be looking similar to
UI ---> Servlet Entry Point 1 ---> Generic Business Logic Handler ---> Specific Business Logic Handler --> System Services Handler ---> System Services
Instead of UI, now we have Queues/Crons calling the system, but generally, as was in my case, the cron was calling code that was more 'internal', for example, send-mail is implemented as a queued task which needs to directly call the System Service Handler bypassing two business logic layers. Similarly, ftp-today's-transactions is a cron that needs to directly call System Services bypassing the business logic layers.
It makes sense to NOT directly call System services from servlet entry point 1, just because you happen to have it at hand and configured in web.xml. It makes more sense to create another entry point for queues and crons which are more 'internal'.
The code then resides in the next level class (called Handlers, sometimes) And you can continue to maintain the hierarchy of layers if you are using packages to enforce it.
You will then not feel bad about calling something sys level directly from servlet level as this will be a specifically secure and separate access interface defined to be calling direct.
Just to make it more intuitive, my two servlets are called
Thin - Thin Http Interface on NudeBusinessObjects [All BOs extend this, and there is a non Http interface]
Thiq - Thiq Http Interface on Queues
Thin just ensures the required parameters are present and passes to handler. It always calls com.mybusiness classes which in turn call com.mysystem classes if they need to.
Thiq has more code, needs secure credentials even on automatic, does more complicated validations and generally has defined high level behaviour for failures across crons/tasks. It always calls com.mysystem classes.
Just my two cents. It isn't too big a thing and if you only keep one entry point and achieve the same effect by writing things in handlers, or even servlets, it doesn't cause end of the world. It just looks ugly when you make an architecture diagram.

How is threading done for Google Cloud Endpoints handlers in Java?

I'm noticing some strange behavior in my app that smells like a lack of thread-safety. I'm working on reproducing it, but in the meantime I wanted to ensure I'm making the right assumptions about how the class that contains my endpoint handlers is used from a threading perspective. Most of what happens is opaque to me, because I'm not the one instantiating the class in the first place. To state the obvious, it must be some black magic in Endpoints.
MY ASSUMPTION
An instance of the class that holds my endpoint handlers is created for every single request that comes into my app. Based upon that assumption, it's ok for that class to have non-thread-safe objects that get used by my handlers.
MY FEAR
The instances of Endpoint handler classes are reused across requests.
So, which is it? Regardless of the answer, I think it would make sense for me to remove the ambiguity in my app and assume the worst, because I don't think I have any control over how Endpoints behaves. In my case, I'm creating a JDO/DataNucleus PersistenceManager (not thread-safe) when constructing the class housing my endpoint handlers. I should probably just create it in each handler as a local, or use a ThreadLocal.
I can probably also fashion a test to prove one or the other. I'll post back an answer to my own question if I do.

How to determine JAX-RS resource paths programatically?

Suppose I have a set of JAX-RS locators and sublocators, like the following:
#Path("/users")
public class UserListResource {
#Path("/{id}")
public UserResource getCustomer(#PathParam("id") int id) {
// Find and return user object
}
}
public class UserResource {
#GET
public String get() {...}
}
For example, a UserResource object with the ID 5 would have the path "/users/5". In my system, I have several different resources.
Now the question is: How can the server figure out the path of a given resource? Can I do this programmatically via some JAX-RS API or do I have to implement code that uses reflection? (I know how to do the latter, but would prefer the other approach.)
At the point when I need to know the path, I do not have a request object at all. For example, I have a timer which does some background processing, then changes some entities in the domain model, then informs all clients about the changed entities (including their paths).
I know that within the scope of a request, I can inject a UriInfo object that provides this, but I need to know the path in advance (to inform clients of a change that did not necessarily happen through the JAX-RS resource).
I don't want to repeat the path information in another place, and I also don't want to have a set of path fragment constants for each resource type (in this case "/users" and "/{id}").
As I read your question, you need to build a URI knowing only the resource class and the id parameter.
It can be done using the UriBuilder class as in:
UriBuilder builder=UriBuilder.fromResource(UserListResource.class);
URI uri=builder.path(UserListResource.class,"getCustomer").build(5);
It uses reflection under the hood, so it is not so easy to refactor, but it is all it is available at the moment.
Overall, be aware that something sounds rather strange with the architecture of your application. It's hard to put a finger on, but the pattern of questions you are asking is raising a number of red flags about how you're going about this. Be aware that if you are seeking to create a RESTful API to your application that you may need to stop, take a few steps back, and rethink what you are trying to do.
To your explicit questions…
Now the question is: How can the server figure out the path of a given resource? Can I do this programmatically via some JAX-RS API or do I have to implement code that uses reflection? (I know how to do the latter, but would prefer the other approach.)
The server knows the path, as that's always supplied by the user and is used to navigate through the collection of resource classes that make up your application. If you need a UriInfo instance for a particular call, you should inject it as part of that specific call:
#GET
public String get(#Context UriInfo info) {...}
Any information required from the outer context (e.g., what the resource's ID is) is best passed in during construction. You can reparse it out of the URL (obtainable from the UriInfo) again, but that's probably the wrong approach.
Otherwise, if you're doing something much more complex then you need to be more specific in your question.
At the point when I need to know the path, I do not have a request object at all. For example, I have a timer which does some background processing, then changes some entities in the domain model, then informs all clients about the changed entities (including their paths).
I know that within the scope of a request, I can inject a UriInfo object that provides this, but I need to know the path in advance (to inform clients of a change that did not necessarily happen through the JAX-RS resource).
How are you going to have the clients be informed? There's normally no mechanism to push messages from the server to the clients, and clients are typically firewalled so that they can't directly host a service.
Theoretically, you could associate (explicitly, by URL) each resource with its own RSS feed to which a client could listen to if they chose. You wouldn't be able to force clients to listen, but you could give them the option to do so. If you go this route, you don't need to know the UriInfo “ahead of time” as the location information will be present at key times (i.e., at resource creation) and afterwards you're just referring to something that you have control over.
But that's just one way to do it and it adds a lot of complexity; you'd only do it if it was critical to your application. It's often simpler to just have clients poll from time to time. (Note that some sorts of modifications are inherently very destructive; particularly altering the ID or deleting the resource. Don't expect things to cope smoothly with those.)
I don't want to repeat the path information in another place, and I also don't want to have a set of path fragment constants for each resource type (in this case "/users" and "/{id}").
Tough. Repeating information in multiple places, provided you draw it consistently from a single source, is a common practice. There's nothing actually wrong with it.
As I understand your question, you want to know the path as the request is coming in but before it hits your resource; are you open to using Servlet Filters?
JAX-RS specific filters are only supported in 2.0
For the record: after I had posted the question, I thought about our architecture a bit more and came to the conclusion that sending URLS is not as useful as I thought. The application has to know some details about the application structure anyway:
Continuing the example above: even if the client did not know the URL pattern for individual users, it must assume that there is a list of users and know its URL; it also has hard-coded knowledge what dialog to display for editing a user etc.
So all in all, attempting to tell the client (most) URLs it needs is not worth the effort. Instead, we decided to go with a custom API definition file which includes data about the resource contents and their URL scheme. This file is used to generate the following:
the server-side resource classes with the correct JAX-RS annotations
a URL scheme specification document for other developers to code against
classes for our own client (including the URL know how, e.g. user with ID 5 has the URL ...), so we don't have to worry about inconsistencies between our client and server.
This approach has the following advantages:
The need for the server to figure out the URLs from the annotations vanishes, as the client can now do that on its own once it receives a notification that includes the object ID.
We don't have to worry about inconsistencies between our client and the server, as all information is drawn from a single source.
We have one source for the API definition under version control which can be used to verify backwards compatibility with older releases.
Note:
I would probably not claim that the resulting API stays "faithful" to the idea of RESTful webservices, but it works for us and the elements that it borrows from "actual" REST architectural style should make the API clearer and easier to learn than a traditional contract-first webservice.

Java Spring MVC stateless-to-stateful handover

Although I have tagged this as a java/spring question it can be easily asked of any mvc framework with stateless controllers. I know rails uses simple stateless controllers for instance so perhaps you guys know how to best solve this problem. I can best describe the problem with java/spring mvc which is the implementation - forgive the java jargon.
The issue
We are having trouble coming up with a satisfactory way of performing stateless-to-stateful handover in spring mvc.
In essence given a structure like:
Model: Unit
With the states: withdrawn, available, unavailable
And the operations: getOutline() and getHelp()
Controller: UnitController
with operations: displayOutline() and displayHelp()
We need a way to check the state of the unit before we execute the operation displayOutline() (because the unit itself may be withdrawn and so the user should be forwarded to a withdrawn page).
We have tried to do this a number of ways including:
The dead simple way (any language)
All methods in the controller that require an ‘available’ state unit call a method isAvailable() in the first line of its implementation. Obviously there lots of replication here, it reeks.
The AOP way (Java specific)
An #Around advice can be created called UnitAccess which does the check and reroutes the control flow (i.e. instead of calling proceed() which would invoke the underlying method it calls another method on the controller). This seems like a hack and not really what AOP if for, it does remove the replication but adds complexity and reduces transparency.
An Interceptor (Provided by servlet architecture but probably doable in other frameworks)
Which checks the unit state and essentially changes the actual URL call. Again this does not seem right. We don’t like the idea of invoking model logic before getting to a controller.
We have thought about
Command Pattern
Creating a command pattern structure which (with the use of inheritance) can return a withdrawn view or valid displayOutline view. As the execute method will perform the checks in a super()call and the specific logic inside the concrete commands. Ie creating a object structure like
DisplayOutlineCommand extends UnitCommand
public void execute(){
super();
// must be ok, perform getOutline()
}
And finally, using a custom Exception
Calling getAvailableUnit() on a service level object which will do the checks for availability, etc before returning the unit. If the unit is withdrawn then it will throw a UnitWithdrawnException which could be caught by the servlet and handled by returning an appropriate view. Were still not convinced. We are also not hot on the idea of using an exception for normal flow control.
Are we missing something? Is there an easy way to do this under spring/another stateless controller framework?
Maybe I'm missing the point, but why should a user come to the controller if the Unit is withdrawn?
I would argue it is best to ensure that normally pages don't link to a controller that require the Unit to be 'OK', if that Unit is not 'OK'.
If the state of the Unit changes between the time the referring page is rendered and the actual call comes in to the controller (it is not longer 'OK'), then the use of an exception to handle that event seems perfectly fine to me (like having an exception when an optimistic locking error occurs).
Perhaps you haven't described the whole problem, but why not put the check in displayOutline() itself? perhaps route to a displayOutlineOrHelp() method, which looks essentially like
ModelAndView displayOutlineOrHelp(...) {
Unit unit = ... //code to get the unit the request refers to
return unit.isAvailable() ? displayOutline(...) : displayHelp(...);
}

Categories