The company I work for, use Java Play Framework. What I think mysterious is how can play retrieve the current session to me. As I see from source code,
package play.mvc;
public abstract class Controller extends Results implements Status, HeaderNames {
public static Request request() {
return Http.Context.current().request();
}
public static Session session() {
return Http.Context.current().session();
}
// ...
}
I found such class very strange, as all the methods are static methods. And I do not understand how Play can get the correct session in handling concurrent request (multi-thread environment ?).
In such case, how can Play handle / retrieve the session information correctly? Note that I can retrieve the session in the beginning or at the end of each Action (which also affect time). And in such case, how can Play retrieve the session correctly using a static method?
Or am I missing something here? It will be cool if one can tell me how Play can make such retrieval work. Thanks.
P.S. I am using quite a legacy Play Version, Play 2.2.0 in my work place and not learning Scala yet.
Related
Our application calls many external API's which take a session token of the current user as input. So what we currently do is in a controller, get the session token for the user and pass it into a service which in turn might call another service or some API client. To give an idea, we end up with something like this (example is .NET but something similar is I think possible in Java)
public IActionResult DoSomething(string something)
{
this.someService.DoSomethingForUser(this.HttpContext.SessionToken, something);
return View();
}
And then we have
public class SomeService
{
private readonly IApiClient apiClient;
public SomeService(IApiClient apiClient)
{
this.apiClient = apiClient;
}
public void DoSomethingForUser(string sessionToken, something)
{
this.apiClient.DoSomethingForUser(sessionToken, something);
}
}
It can also happen that in SomeService another service is injected which in turn calls the IApiClient instead of SomeService calling IApiClient directly, basically adding another "layer".
We had a discussion with the team if it isn't better to instead of passing the session token, inject it using DI so you get something like this:
public IActionResult DoSomething(string something)
{
this.someService.DoSomethingForUser(something);
return View();
}
And then we have
public class SomeService
{
private readonly IUserService userService;
private readonly IApiClient apiClient;
public SomeService(IUserService userService, IApiClient apiClient)
{
this.userService = userService;
this.apiClient = apiClient;
}
public void DoSomethingForUser(string something)
{
this.apiClient.DoSomethingForUser(userService.SessionToken, something);
}
}
The IUserService would have an IHttpContextAccessor injected:
public class UserService : IUserService
{
private readonly IHttpContextAccessor httpContextAccessor;
public UserService(IHttpContextAccessor httpContextAccessor)
{
this.httpContextAccessor = httpContextAccessor;
}
public string SessionToken => httpContextAccessor.HttpContext.SessionToken;
}
The benefits of this pattern are I think pretty clear. Especially with many services, it keeps the code "cleaner" and you end up with less boilerplate code to pass a token around.
Still, I don't like it. To me the downsides of this pattern are more important than its benefit:
I like that passing the token in the methods is concise. It is clear that the service needs some sort of authentication token for it to function. I'm not sure if you can call it a side effect but the fact that a session token is magically injected three layers deep is impossible to tell just by reading the code
Unit testing is a bit more tedious if you have to Mock the IUserService
You run into problems when calling this in another thread, e.g. calling SomeService from another thread. Although these problems can be mitigated by injecting another concrete type of IUserService which gets the token from some place else, it feels like a chore.
To me it strongly feels like an anti pattern but apart from the arguments above it is mostly a feeling. There was a lot of discussion and not everybody was convinced that it was a bad idea. Therefor, my question is, is it an anti pattern or is it perfectly valid? What are some strong arguments for and against it, hopefully so there can be not much debate that this pattern is indeed, either perfectly valid or something to avoid.
I would say the main point is to enable your desired separation of concerns. I think it is a good question if expressed in those terms. As Kit says, different people may prefer different solutions.
REQUEST SCOPED OBJECTS
These occur quite naturally in APIs. Consider the following example, where a UI calls an Orders API, then the Orders API forwards the JWT to an upstream Billing API. A unique Request ID is also sent, in case the flow experiences a temporary problem. If the flow is retried, the Request ID can be used by APIs to prevent data duplication. Yet business logic should not need to know about either the Request ID or the JWT.
BUSINESS LOGIC CLASS DESIGN
I would start by designing my logic classes with my desired inputs, then work out the DI later. In my example the OrderService class might use claims to get the user identity and also for authorization. But I would not want it to know about HTTP level concerns:
public class OrderService
{
private readonly IBillingApiClient billingClient;
public OrderService(IBillingApiClient billingClient, ClaimsPrincipal user)
{
this.billingClient = billingClient;
}
public async void CreateOrder(OrderInput data)
{
this.Authorize();
var order = this.CreateOrder(data);
await this.billingClient.CreateInvoice(order);
}
}
DI SETUP
To enable my preferred business logic, I would write a little DI plumbing, so that I could inject request scoped dependencies in my preferred way. First, when the app starts, I would create a small middleware class. This will run early in the HTTP request pipeline:
private void ConfigureApiMiddleware(IApplicationBuilder api)
{
api.UseMiddleware<ClientContextMiddleware>();
}
In the middleware class I would then create a ClientContext object from runtime data. The OrderService class will run later, after next() is called:
public class ClientContextMiddleware
{
public async Task Invoke(HttpContext context)
{
var jwt = readJwt(context.Request);
var requestId = readRequestId(context.Request);
var holder = context.RequestServices.GetService<ClientContextHolder>();
holder.ClientContext = new ClientContext(jwt, requestIO);
await this.next(context);
}
}
In my DI composition at application startup I would express that the API client should be created when it is first referenced. In the HTTP request pipeline, the OrderService request scoped object will be constructed after the middleware has run. The below lambda will then be invoked:
private void RegisterDependencies(IServiceCollection services)
{
this.services.AddScoped<IApiClient>(
ctx =>
{
var holder = ctx.GetService<ClientContextHolder>();
return new ApiClient(holder.context);
});
this.services.AddScoped<ClientContextHolder>();
}
The holder object is just due to a technology limitation. The MS stack does not allow you to create new request scoped injectable objects at runtime, so you have to update an existing one. In a previous .NET tech stack, the concept of child container per request was made available to developers, so the holder object was not needed.
ASYNC AWAIT
Request scoped objects are stored against the HTTP request object, which is the correct behaviour when using async await. The current thread ID may switch, eg from 4 to 6 after the call to the Billing API.
If the OrderService class has a transient scope, it could get recreated when the flow resumes on thread 6. If this is the case, then resolution will continue to work.
SUMMARY
Designing inputs first, then writing some support code if needed is a good approach I think, and it is also useful to know the DI techniques. Personally I think natural request scoped objects that need to be created at runtime should be usable in DI. Some people may prefer a different approach though.
See in dotnet the area that I am an expert is not an anti standard on the contrary it is the model that many adopt but it is not a model that I would follow for the following reasons
it is not clear where is the token for those who read and use it being an anti clean code
you load important information in a place that is frequently accessed by the framework in the case of .netCore
your classes will reference a large property carrying a lot of unnecessary information when you could have created a more clean model that costs less memory and allocation time, I'm saying this because the HttpAcessor carries all the information relevant to your request
As I would take care of readability (clean code) and improve my performance
I would make a middleware or filter in my flow mvc where I would do the authentication part and create a class like:
public class TokenAuthenciationValues
{
public string TokenClient { get; set; }
public string TokenValue { get; set; }
}
Of course my method is an example but in my middleware I would implement it by loading its token values after calling the necessary apis (of course this model needs an interface and it needs to be configured as .AddScoped() in the case of .net)
That way I would use it in my methods only instantiating my ITokenAuthenciationValues in the constructor and I would have clear and clean information loaded in memory during the entire request
If it is necessary in the middle of the request to change the token any class can access it and change its value
I would have less memory allocated unused in my classes since the IHttpAcessor contract the ITokenAuthenciationValues only has relevant information
Hope this helps
I have a problem with establishing a transaction manager/scope for my REST API (JAVA), I have below functions in my API back end and i want to excute all below functions as one transaction,
Call third party WS end point
Decrypt the response
Save the response in to DB1
Save the response in to DB2
I want to make sure all above steps are completed or rollback if any one fail, I have enough information to do the rollback, but i have no idea what would be the best practice to implement proper transaction management mechanism, because above mentioned steps happen in 3 separate classes per API call,
This is a pseudo code for my class structure
class CallWS {
public People callThWS() {
// functions related to call third party WS and decryption (step 1,2)
}
}
class People peopleServices {
public People getPeopleData() {
callThWS ppl= new callThWS();
People pplObj = ppl.callThWS();
// save to DB1, (step 3)
return pplObj;
}
}
class People peopleContr {
public People getAllPeople() {
peopleServices ppSer= new peopleServices();
People pplObj2 = ppSer.getPeopleData();
// save to DB2, (Step 4)
return pplObj2;
}
}
Please help me on this,
Thanks
What you need is Distributed Transactions(XA). Check for examples of various transaction managers which support XA. Check this article for using XA provider in standalone applications(Warning: Old article).
If you control sources of all classes listed and you can refactor your code the way you have a single entry point, you can do it quite easily, except the call to an external web service. The pseudo code is below.
Here we should agree that all resources your are calling in your methods are transactional. As I mentioned earlier call to an external WS would not fall to that category because calls to external web services are not transactional by their nature. Again if you do not change data withing a call to the external service you may consider just leave it outside transaction. You still have a bit of control. Like rolling back transaction in case a call to the external service was unsuccessful and as far as you have not changed anything on the other side, you may not care about rolling back a transaction there.
However you still have some options for a transaction call to an external WS call like Web Services Atomic Transactions, but I bet you would need control for sources and maybe even environment on the other side. In such a lucky circumstances you would rather want to achieve it by avoiding the WS call.
class RestAPIEntryPointResource {
#Inject
CallWS callWS;
#Inject
PeopleServices peopleServices ;
#Inject
PeopleContr peopleContr;
/*Put some transaction demarcation here.
If your class is an EJB, it is already done for you.
With Spring you have various options to mark the method transactional.
You also may want to take a manual control, but it look redundant here. */
public void entryPointMethod() {
callWS.callThWS();
peopleServices.getPeopleData();
peopleContr.getAllPeople();
}
}
class CallWS {
public People callThWS() {
// functions related to call third party WS and decryption (step 1,2)
}
}
class PeopleServices {
public People getPeopleData() {
..........
}
}
class PeopleContr {
public People getAllPeople() {
.........
}
}
First of all, I am fully aware of the authentication modules that are available to Play. That said, I am unable to implement even the simplest example code from let's say SecureSocial. With a little bit of research it became clear that a lot of things were broken in their example code provided here when the Play Framework updated to version 2.3.x.
With the help of online docs and the excellent video tutorial by Philip Johnson on implementing standard (unsafe) authentication I did succesfully implemented the following:
// Class which is used by the #Security annotation
public class Secured extends Security.Authenticator {
#Override
public String getUsername(Context ctx) {
return ctx.session().get("auth");
}
#Override
public Result onUnauthorized(Context ctx) {
return redirect(routes.Application.login());
}
}
// Controller class that serves routes
public class Application extends Controller {
#Security.Authenticated(Secured.class)
public static Result index() {
return ok(index.render("Your new application is ready."));
}
public static Result login() {
session().clear();
session("auth", "a1234"); // dummy data simulating succesful login
returning redirect(routes.Application.index());
}
}
I need to ultimately implement a safe login system to authenticate users.
My question is two-sided. What would be the better of the following: 'reinventing the wheel' (at least partly) by taking the working code base and improving it or give implementing one of the authentication modules another shot?
We all do not like reinventing the wheel, that said, I have a much better chance of succesfully compiling when I made it myself it seems...
I am aware that for a wholesome security-in-depty (a.k.a. layered security) a secure connection implementation is also needed (HTTPS with TLS1.2` at the time of writing). This is beyond the scope of my question.
I don't know if there's a right answer to this question. Whether to build your own framework or to try an existing framework (which might not work perfectly) is a matter for your own judgement. Personally, I'd probably use SecureSocial as a starting point but then write my own code if I couldn't get it working. It sounds like this is the approach you've already tried.
To use SecureSocial you'd probably need to check out the master branch and build from source. It might be hard to use if the examples are out of date, but then again writing your own auth code is difficult too.
Looking through the Play documentation for Java I noticed the following block of code:
public static Result show(Long id) {
Client client = Client.findById(id);
return ok(views.html.Client.show(client));
}
Source: http://www.playframework.com/documentation/2.1.0/JavaRouting
I am having some trouble understanding the second line, my understanding of Java Object creation is a typical constructor looks like the following:
Person john = new Person();
What is the second line doing? Creating a Object called client from Class called Client, also what is Client? It doesn't appear to be a part of the Play Framework, certainly I cannot find anything in JavaDocs.
Thanks
Edit:
I found this to be a good point of reference for the answer (http://docs.oracle.com/javase/tutorial/java/javaOO/classvars.html)
Also I think the class Client comes from the following documentation (http://www.playframework.com/documentation/1.1.1/controllers) with Client being just a example model class, the new documentation probably needs updating to clear up this confusion.
Pretty clearly, the class Client has a static function of findById, which takes a Long and returns a Client. Static functions are functions that are defined without any access to object properties, and therefore can be accessed through the class name, rather than having to be accessed through an object. Most likely, the class has a static property containing a collection of all clients in the system by index, and findById grabs an existing Client from that list.
I really have no idea where the class Client is defined, however. I've also made a quick look around for it, and couldn't find it in the obvious places.
There must be a static method called show(Client) on the views.html.Client class that returns some object. That object is passed into an ok(whatever) method, and that ok method returns a Result object.
You're missing some basic knowledge/experience. The sample you gave has nothing to do with routes and in this snippet only first line is important, second is just some hypothetical usage. De facto it could be just...
public static Result show(Long id) {
return ok("You want to display details of client with ID: " + id);
}
Although #BenBarden explained what is that mean correctly , this static method isn't declared anywhere, it's (again) hyphotetical usage of some ORM. For an example the real usage with Ebean's model will be:
Client = Client.find.byId(id);
Of course you can also declare own method in your Client model and name it the same as in the sample, however it will be just only wrapper:
public static Finder<Long, Client> find
= new Finder<>(Long.class, Client.class);
public Client findById(Long id) {
return find.byId(id);
}
Conclusions
You need to examine some samples available with your Play sources to get familiar with some basic syntax, fortunately you'll find it easy.
DO NOT MIX documentation from Play 1.x with Play 2.x they are not compatible!
So I'm writing a web service architecture which includes FunctionProvider classes which do the actual processing of requests, and a main Endpoint class which receives and delegates requests to the proper FunctionProvider.
I don't know exactly the FunctionProviders available at runtime, so I need to be able to 'register' (if that's the right word) them with my main Endpoint class, and query them to see if they match an incoming request.
public class MyFunc implements FunctionProvider{
static {
MyEndpoint.register(MyFunc);
}
public Boolean matchesRequest(Request req){...}
public void processRequest(Request req){...}
}
public class MyEndpoint{
private static ArrayList<FunctionProvider> functions = new ArrayList<FunctionProvider>();
public void register(Class clz){
functions.add(clz);
}
public void doPost(Request request){
//find the FunctionProvider in functions
//matching the request
}
}
I've really not done much reflective Java like this (and the above is likely wrong, but hopefully demonstrates my intentions).
What's the nicest way to implement this without getting hacky?
Do not let the FunctionProviders self register. Bootstrap the endpoint through some application init. call with a list of FunctionProviders. That way you can configure priority (what if two providers both claim they can process a request?). The way you set it up now you need to invoke the class somehow to trigger the static constructor, too indirect.
If detecting whether or not a FunctionProvider supports a given request is trivial consider making it part of configuration. If this is in the request map it to that FunctionProvider. This would seperate concerns a bit better. If the detection is complicated consider doing it in seperate classes from the FunctionProvider.
By configuring a delegate/function pointer you can possibly prevent from needing a FunctionProvider altogether (not sure if/how Java supports delegates).