Play! framework uses a <lot> of statics

JavaStaticPlayframeworkPlayframework 1.x

Java Problem Overview


Waaah, the Play! framework has so many static methods. Where I go to school, we were told never ever to use any statics, yet Play! uses it like there's no tomorrow. Is that somehow okay? If so, why?

We (7 people and I) are planning to use the Play! framework for a project involving a web app. We decided to do it with Play! because it looks quite fun to do, all of us already know Java and the assignment is pretty hard so we wanted to focus on the actual assignment rather than also learning how to program in a different language.

We were always told, however, NEVER EVER to use 'static's in any Java program we developed, but when I look at Play! ... Well... about half the methods are static. </exaggeration>

I suppose, at the very least, we could use singleton objects (by using Scala, for example ^^) in order to program our project, but I'm quite concerned at how many statics there actually are in framework itself.

So, should I be concerned about this? Did the way the Play! developers programmed it make it so that all these statics don't pose a problem?

(For example, [this thread][1] has a rant about why static members should be avoided at all costs.)

[1]: http://www.allegro.cc/forums/thread/586752 "this thread"

Java Solutions


Solution 1 - Java

Play uses static methods only when it makes sense:

  • in the controller layer, because controllers are not object oriented. Controllers act as mapper between the HTTP world (that is stateless, and request/response based) and the Model layer that is fully object oriented.
  • in the model layer for factory methods, like findAll(), count(), create() which of course don't depend of any particular instances
  • in some play.libs.* classes that provides purely utility functions

Solution 2 - Java

Play framework is not a good demonstration of when using statics is appropriate, nor it proves that your teacher was wrong. Play is kind of cheating, solves the issues of statics outside the Java language.

The key problem is that you have to process multiple HTTP requests in parallel, and static fields are "global". So you will need one instance per thread (or even better, one instance per HTTP request) for certain things, yet some of those things are returned by static methods in Play. That works because Play! uses ThreadLocal-s heavily, and so it solves a problem of statics outside the Java language. But that's not everything. Some say that controller methods are rightfully static. Sure, but in plain Java it would be inconvenient, as then you can't access request-specific data without some kind of prefix, like req. in req.session, and then you still have to get req from somewhere, like as a parameter of the static controller method, which is even more hassle. Yet in Play you can you just directly write session and like, they are just static fields. That's because Play uses bytecode instrumentation to change all those static field references to something smarter. Again, a solution outside the Java language. Those are not static fields at the end.

So, in general, avoid non-final statics. Play does the magic for you though, so don't afraid of them in this case.

Solution 3 - Java

From a very brief look, I'd say it kind of makes sense: web requests are stateless, so there is no object to receive the request (=the method). Thus, mapping an URI such as "/articles/archive?date=08/01/08&page=2" to a static method called archive() on, I guess, your application class makes sense.

Solution 4 - Java

EDIT Now in Play 2.4, the injection is done automatically. So just adding @ at the beginning of the controller path in the file routes will make the trick:

GET     /                  @controllers.Application.index()

For older versions (2.1 to 2.3) you will have to override getControllerInstance in the Global class, like explained in the Documentantion.

Solution 5 - Java

As with anything in programming, never ever is never the right answer. Just like always. There are always exceptions and the right answer is always 'it depends'.

It's true that in pure OO (which I'm all for) there is very little room for statics. But it's also true that sometimes they just make sense.

The classic example is utility methods. Sure, it would be better if we could just append our abs() method to Integer. But we can't; so we're stuck with Math.abs(int i).

I tend to think it's just correct to make a method static when it has nothing to do with the instance itself. For instance, in a class Person, you could have a method that takes a list of people, and returns the number of people that have a birthday today. Maybe you can only do this in the class itself if the data needed to do the calculation is private (something an OO purist would understand ;)) but still the method clearly has no relation to a single Person instance.

Another thing is internal classes. You often want to make them static if you don't need the relation with the containing type.

I've never seen Play! but if you say that over 50% of it is static, then I'm guessing it was probably badly designed. That's no exception; a lot of frameworks are. Don't let it get you down. Definately don't learn from it!
But if it works you can still use it.

Solution 6 - Java

The main problem is that static methods only have access to other static methods and fields, which results in 'static cling' whereby the static methods have to rendezvous with the rest of the application (which contains its collaborators) via common static field(s), which leads to inflexibility.

Disclaimer: I don't know much about 'play!'

Solution 7 - Java

Static controller methods are certainly an area of concern with the Play! framework, and after having done some testing, it is the main reason for me not doing Play! in projects. You can actually see this where in FOSS projects where Play! is used. There is little or no Controller testing. The reason, with static methods, DI becomes difficult. This is where they should have spent even more time with ASP.NET MVC, from where Play! already takes a bit of inspiration.

Typically you have a constructor like this:

public HomeController( IService service ) {
   _service = service;
}
public Index() {
   var data = _service.getData();
   return View( data );
}

Then you use DI to inject the IService implementation into the Controller. The point being that in your tests, you can instantiate the IService just prior to running the Controller, and then test the result based on the IService you just produced.

In Play this becomes very hard. Thus Controller unit testing becomes hard. That is, to me, a significant problem. I would therefore tend to look for other frameworks than Play! in the Java world. Heck, why not go with the original and just use JRuby?

Solution 8 - Java

Statics method in play are mainly used in controllers action methods. These methods are meant to just fetch the necesary data from the model and expose it to views.

They correspond somehow to each possible http request, and, just like those http request are completely stateless.

On structural programming you have procedures on the one hand, and variables on the other, but on OOP paradigm you treat procedures and variables as a whole.

That is, you have and object with instance methods (procedures) and instance variables.

But controller actions are stateless, that is they get all there variables from the request (maybe also from the cache, but in that case you need some sort of session id that finally comes from the request). So controller actions are just like stateles procedures, and that's why they don't particularly fit in the OOP paradigm, as models do.

Solution 9 - Java

>I suppose, at the very least, we could use singleton objects

Singleton in Java does not makes much difference than using all static. There is not much to store as state as well. I think you should not worry about it.

>So, should I be concerned about this? Did the way the Play! developers programmed it make it so that all these statics don't pose a problem?

It would not. In fact, it's alright.

Solution 10 - Java

Im also surprised by the number of static methods in play, but why not if it works fine...

Actually i don't agree with your teacher.

If an object has no state (ie global variables) but just contains methods for exemple, it doesn't give you any benefits to use an object rather than static methods. Except if you are planning to add a state later (state that should not be shared), or if you are using an interface and want to be able to switch easily the implementation, it's easier to use static methods...

JDK itself, apache commons or many frameworks are including static methods:

  • StringUtils
  • Pattern.matches(regex,input)


Actually i guess you wonder what's about classes like JPA.java: https://github.com/playframework/play/blob/master/framework/src/play/db/jpa/JPA.java

They use only static methods and keep a static state. This could be strange, but actually for me it's a bit like using a singleton except the methods are used on a static context instead of an object. The main difference is that you don't have to call getInstance() everytime.

I think this was designed like that for usability, because it is not user friendly to call "getInstance" and it's cool to be able to get easily a session everywhere (linked to the thread) instead of injecting the sessionFactory everywhere with xml or autowiring...

Your professor perhaps tells you to avoid using statics because it can be dangerous for your design if you don't use them right. But notice in many cases, replacing static methods by a singleton doesn't make your design better. Even if you now call the methods on an instance method, objects will still be tightly coupled...

So perhaps a rule should be to avoid using statics except when you don't really care about a tight coupling.

  • On this case, when you call JPA.xxx() methods, your code is tightly coupled to play framework's JPA class. But i don't think play is designed so that you would be able to easily switch from one framework to another without at least some rework...

  • It's a big difference with EJB3 spec or stuff like that: if the EJB3 entity manager's methods where static, you would be forced to tightly couple your code to the implementation by calling HibernateEntityManager.xxx() or ToplinkEntityManager.xxx(). In this case, there is a common interface (and we can't add static methods on interfaces).



  • That class is not part of a specification used on other frameworks.
  • The JPA class has just one implementation: the one done by play. And they probably are not planning to make a second one.
  • Thus a tight coupling to this Play class, while you are using Play framework, seems ok for me.

Solution 11 - Java

Play takes a functional approach, like node.js for example, and arguably makes 'more sense' in Scala than in Java, as the Typesafe Stack is pushing, for example. As other posters have pointed out, Java is being augmented using bytecode instrumentation (a la Aspect J) to behave in a more stateless/functional way; Scala does this by default.

Solution 12 - Java

If you are an Object Orientated Programming purist, you shouldn't use static methods/fields, however they can be used safely, and don't have to be a cause for concern IMHO.

Solution 13 - Java

One of the reasons to use static methods are the static imports which allow you to shorten the notation and make the code more readable. This is specially true when using utility libraries like Guava or Apache Commons in which you might have a lot of static calls.

Non-static controller methods are now supported in Play 2.1 via using controller injection, so it's not very clear why they were not there from start.

Solution 14 - Java

You can now use Spring DI within Play, see https://stackoverflow.com/a/16552598/10433. I'm using it and it works fine so far.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionSaewView Question on Stackoverflow
Solution 1 - JavaGuillaume BortView Answer on Stackoverflow
Solution 2 - JavaddekanyView Answer on Stackoverflow
Solution 3 - JavaunwindView Answer on Stackoverflow
Solution 4 - JavaDidac MonteroView Answer on Stackoverflow
Solution 5 - JavaJoeri HendrickxView Answer on Stackoverflow
Solution 6 - Javauser638455View Answer on Stackoverflow
Solution 7 - JavaTerjeView Answer on Stackoverflow
Solution 8 - JavaopensasView Answer on Stackoverflow
Solution 9 - JavaNishantView Answer on Stackoverflow
Solution 10 - JavaSebastien LorberView Answer on Stackoverflow
Solution 11 - JavaspumeView Answer on Stackoverflow
Solution 12 - JavaPeter LawreyView Answer on Stackoverflow
Solution 13 - JavaAndrey ChaschevView Answer on Stackoverflow
Solution 14 - JavaAndrew SwanView Answer on Stackoverflow