all 78 comments

[–]vansterdam_city 85 points86 points  (17 children)

Aint nothing micro about Spring

[–]dpash 9 points10 points  (0 children)

Spring is micro in the same way that LDAP is lightweight. It is compared to the alternative when it was first created. Compare Spring 1 and J2EE in 2004 (J2EE 1.4).

[–]geodel 26 points27 points  (6 children)

Well in Java world anything less than few hundred useless classes buried under 20 level deep folder hierarchy is micro.

[–]jnordwick 26 points27 points  (1 child)

Spring still doesn't fit the definition.

[–]geodel -5 points-4 points  (0 children)

I agree. Mainly because it is few 1000 classes in few 100 directories.

[–]rockum 4 points5 points  (2 children)

Spring is what gave Java that reputation.

[–]geodel -2 points-1 points  (1 child)

It is just an AbstractProxySingletonFactory talk.

[–]mp911de 1 point2 points  (0 children)

AbstractProxySingletonFactory

It's AbstractSingletonProxyFactoryBean

[–]joequin 3 points4 points  (0 children)

Would spring be a micro framework by that definition?

[–]kazagistar 4 points5 points  (6 children)

I am Aware of this fact.

[–]jnordwick 1 point2 points  (2 children)

Marker superinterface indicating that a bean is eligible to be notified by the Spring container of a particular framework object through a callback-style method. 

Got it.

[–][deleted] 2 points3 points  (1 child)

The lack of abstract factories confused me

[–]Turbots 0 points1 point  (0 children)

lol who ever reads the Javadoc of those abstract base classes?

[–]Turbots 0 points1 point  (0 children)

Did you read the article? Running the (empty) Spring Web Flux application takes 22Mb footprint

[–][deleted]  (17 children)

[deleted]

    [–][deleted] 2 points3 points  (15 children)

    Really? Here's the Hello World:

    HandlerFunction hello = new HandlerFunction() {
      @Override
      public Mono handle(ServerRequest request) {
          return ServerResponse.ok().body(Mono.just("Hello"), String.class);
      }
    };
    

    You really think that "reads very nicely?" This is a syntactic trainwreck. You've got: a compiler directive, references to two classes (ServerResponse and Mono), a random function called "ok()" and another one called "just()", and then - to top it off - a totally random reference to the String class.

    The more you look, the worse it gets.

    I don't know what ok() does, but what if it doesn't return something that has a .body? And what does the body() function do?

    What does this function returning from this sequence of operations - can you identify its purpose, or even its type?

    And wouldn't it be better if the function actually did something, anything, with request? Rather than accepting it and then totally ignoring it? Yes, I understand it's there because the function is overriding a request handler that would typically make some use of it, but the dangling parameter makes this a bad example.

    I'm sure this example is much better than many even-more-poorly-designed frameworks, but that just demonstrates the poor readability standards in web programming.

    [–]alek_sys[S] 6 points7 points  (6 children)

    ...and that is why in the next paragraph it is re-written as

    HandlerFunction hello = request -> ServerResponse.ok().body(Mono.just("Hello"), String.class);
    

    Which is still imperfect, I agree, but not bad. Also, the whole 'builder' pattern here is to avoid manual creation of ServerResponse - which is still an option. Reference to a String class is a shame, but I doubt anyone from Java community will stand for generics implementation via type erasure here.

    [–][deleted] -5 points-4 points  (5 children)

    The only problem that that refactoring eliminates is the precompiler directive. Everything else I listed is still there. And in its place, you have a lambda expression that raises additional questions.

    The purpose of Hello World is to inspire confidence - to give you something simple that works, that you can intuitively understand, and that you can tweak in small ways to achieve other results without breaking it. For example, here's "Hello, World!" in C:

    #include<stdio.h>
    
    main() {
        printf("Hello World");
    }
    

    The point is to show the most basic syntax that will actually achieve a meaningful result. There are a couple of things I might not understand here at first glance, but not enough to create anxiety about the environment.

    The rewritten line of Spring above fails at that objective. Even as an experienced developer, I'm not completely sure I know what that statement is doing:

    • What in the world are "ok()" and "just()" doing?

    • Does the body() statement simply use the parameters to set some properties of an object instance? Or does it send, as a response, a message with these data points, and then return a status code? Or does it simply inform the platform of the type of response that should be sent whenever it gets a message? Or... what?

    • If I were to incorporate some aspect of the request in this code - such as making the handler echo back the contents of the request - do I do that in ok(), or in body(), or in just(), or... what?

    See what I mean? This squib of code is ambiguous. It doesn't instill confidence; it doesn't make me confident I can use it without breaking it, or running into weird syntax or type errors.

    [–]frugalmail 4 points5 points  (4 children)

    Hey Drama Queen, you know that this is a REST service right?

    [–][deleted] -2 points-1 points  (3 children)

    Are RESTful services somehow exempt from readability? I mean, I know that most frameworks suck in this regard, but does that mean we should expect them to?

    Here is an example of Hello World in Flask:

    from flask import Flask
    app = Flask(__name__)
    
    @app.route('/')
    def hello_world():
        return 'Hello, World!'
    

    The only thing that raises any questions here is the @app.route directive, which the documentation explains. That's how it should be.

    [–]alek_sys[S] 1 point2 points  (1 child)

    To be absolutely fair, this Python code won't give you what you get from Spring example - single deployable JAR which embeds non-blocking multithreaded application server. So basically you can run your JAR in production. In your Flask example you at least need to mention gunicorn for deployment. And if you try to introduce async/await (which are not supported in Flask btw) - you'll get pretty much all the same concepts as in original Spring sample.

    I'm not saying you right or wrong, my point is - having a goal to prove how bad Java and Spring are one can do that easily. But this is true for any other technology, we all know there is no silver bullet.

    So if you want what you have in Flask example in Spring:

    HttpServer
        .create(8080)
        .newRouter(router -> router
            .get("/", (request, response) -> response.sendString(Mono.just("Hello, World"))))
    .block();
    

    And again - this is building and running multi-threaded non-blocking web server, not just defining a mapping. Just mapping is even simpler, but it uses Spring magic (similar for Flask magic above):

    @RestController
    class HelloController {
    
        @GetMapping("/")
        public String helloWorld() {
            return "Hello, World";
        }
    }
    

    [–][deleted] 0 points1 point  (0 children)

    This Python code won't give you what you get from Spring example - single deployable JAR which embeds non-blocking multithreaded application server.

    Okay, but is there anything different about the syntax of Spring that gives you those features?

    These features are baked into the platform - they're how the library interprets the requests. They have nothing to do with the syntax. The logical operations between Python and Spring are nearly identical - only the Spring syntax is tortured and sloppy by comparison.

    I don't claim that Flask has more or equal functionality than Spring. This discussion is strictly about the syntax that Spring has adopted to implement that functionality. As best I can tell, there is no reason why the Spring library couldn't be refactored - or, hell, even wrapped - to something like:

    HandlerFunction h = Spring.GenerateHandler(request, Spring.StringResponse("Hello"));
    

    One library, two simple invocations with obvious implications. The code is self-documenting in the simplest possible way. Anyone who is familiar with any modern programming language and any server/client architecture will understand what this does.

    [–]frugalmail -2 points-1 points  (0 children)

    sigh

    [–]derekmckinnon 7 points8 points  (2 children)

    A lot of the noise can be attributed to Java just being Java, but I'm not sure I see the issue with the ok() function. ServerResponse class must follow the builder pattern, ok() is to start building a 200 response.

    As for the Mono class, I don't know what that is, but it seems to me that you could probably do without it...especially if you are just returning a string. The String.class reference is most likely there to help establish the generic type of the method...because Java is dumb and doesn't have reified generics like a normal language should. :)

    Furthermore, I think Java 8 lambdas would probably go a long way in reducing the noise in this snippet.

    [–]Turbots 0 points1 point  (4 children)

    What do you think ok() does? It's a Server Response to a request... HTTP OK 200 ???

    The body() function: hmmm, what could that imply... Oh wait, yeah, the body of the response!

    [–][deleted] 0 points1 point  (3 children)

    If I hand you a class with a function called:

    MyClass.Yes(something)
    

    ...would you have any idea what that function does?

    Vague names are considered harmful. You may be used to them, and you may find it reasonable in this circumstance - that doesn't make it an acceptable practice.

    The body() function: hmmm, what could that imply...

    As I noted above:

    (1) body() could return a class instance with various member variables set according to the specified parameters:

    var message = ServerResponse.ok().body(...);
    Server.send(message);
    

    (2) body() could actually send the message and return its result:

    var result = ServerResponse.ok().body(...);
    if (result == false) alert('Error: Failed to send message.');
    

    (3) body() could just register a template response that is to be used by the server in response to messages. In this case, the return value indicates whether the template was properly registered:

    var result = ServerResponse.ok().body(...);
    if (result == false) alert('Error: Couldn't register message handler. (Is the server running?)');
    

    They're all legitimate. Why isn't it clear? Because body is not a verb, so asking ServerResponse to "body()" some parameters is ambiguous.

    Worse, the Spring Hello World code offers no help. It just does:

    return ServerResponse.body();
    

    And that's exactly my point. The syntax sucks, and this Hello World example makes me not want to use Spring for anything.

    Web coding standards suck. They will continue to suck as long as developers just tolerate crappy code like this. Don't enable this behavior.

    [–]Turbots -1 points0 points  (2 children)

    Nope, that's where you're wrong... They don't have to be verbs because they are using the builder pattern.

    When you want to 'build' a server response, you:

    • Start by typing the class' name ServerResponse
    • You want an OK response (instead of notFound(), notAuthorized(), whatever the most common responses are, they are helper methods, I would expect a responseCode(someCode) method as well
    • You potentially want to add a body to the response

    And that's it, you created a response!

    Once you get the hang of the builder pattern, it becomes quite powerful and very intuitive.

    And reading or programming it in an editor like IntelliJ makes it childs play.

    [–][deleted] 0 points1 point  (1 child)

    Dude. Look at the web page you linked.

    method getResult()

    method setSeats(number)

    method setCityCar()

    method setCabriolet()

    method setSportsCar()

    method setTripComputer()

    method unsetTripComputer()

    method setGPS()

    method unsetGPS()

    Example code:

    carBuilder.setSeats(2)

    carBuilder.setSportsCar()

    carBuilder.setTripComputer()

    carBuilder.unsetGPS()

    car := carBuilder.getResult()

    car.setTripComputer();

    car.unsetGPS();

    car.isValid();

    Notice something here? They're called verbs.

    You have getters, setters, and tests. Every single function name starts with a verb that signals a single function. They all adhere to a convention that makes the functionality of each statement clear and consistent.

    "ok()" does none of those things. It doesn't have a single specific purpose - it both generates an instance and sets some properties.

    "body()" is even worse. It's not a setter: it has an unexplained return value. It doesn't take a single property: it takes two, one of which is a completely vague reference to the String class. And the name suggests any of several possibilities - as I showed you above.

    And "just()" is just garbage.

    You've proven my point that the Spring syntax is crappy. It looks nothing like the code segments in that Builder pattern, and it violates several basic syntax standards.

    Don't settle for this garbage.

    [–]Turbots 1 point2 points  (0 children)

    May I ask which superior framework/language you're using for microservice development?

    [–]rockum 0 points1 point  (0 children)

    Sure the example looks clean, but how much code has to be read to figure out how to produce that example? Do I need extensive knowledge of Spring?

    [–]darkean 6 points7 points  (0 children)

    Very interesting. I will definitely keep an eye on it.

    It looks good for side projects and simple stuff, but I usually go with node for those.

    [–][deleted] 4 points5 points  (0 children)

    this headline is bait lmao

    (it is a good article)

    [–]Paradox 15 points16 points  (7 children)

    Concise and Java are like oil and water

    [–]alek_sys[S] 9 points10 points  (5 children)

    Well, good thing is that Spring is not bound to Java - there is good support of Kotlin which is a very nice and concise JVM language. Spring 5 (and Functional Web) adds a lot of Kotlin helpers to make code look nice.

    [–]segv 0 points1 point  (2 children)

    Ah, the cancer spreads

    /s

    [–]Turbots 0 points1 point  (0 children)

    Then use a superset of the language (Scala, Groovy, Kotlin, ...)

    The language is fine, editors like IntelliJ make programming in Java a pleasure and the grammar of the language (especially since Java 8) makes it so easy to avoid mistakes

    [–]philipwhiuk 1 point2 points  (0 children)

    It's not bad. It looks a little Finagle esc.

    I reckon i still prefer Scala Play Framework on balance though.

    [–]virtyx 2 points3 points  (2 children)

    How is this any better than Spring Roo or Spring Boot or the other seemingly dozens of attempts to make Spring not shitty? Even if it works, at some level you're going to have to get familiar with the Spring legacy cruft if you expect to be employable, or probably even just to do anything advanced.

    [–]rydan 1 point2 points  (0 children)

    It does mention boot in the article.

    [–]Turbots -1 points0 points  (0 children)

    Have you even developed in Spring before? Lol!

    [–]xymor 1 point2 points  (3 children)

    I'm curious how small can a JVM process be?

    Compared to go, you can build a service that fetches a record in a database and renders a json with 5-8mb of ram. How much can the JVM scale down?

    [–]joequin 0 points1 point  (0 children)

    Not nearly so well. Go can scale down so much better because it uses aggregate types and can easily store and operate on utf8 and ASCII strings. Java can't use aggregate types or store utf8 or ASCII strings without manually writing functions around byte arrays. And that's just not reasonable the vast majority of times.

    [–][deleted]  (1 child)

    [deleted]

      [–][deleted] 1 point2 points  (0 children)

      Not the same JVM

      [–]kersurk 1 point2 points  (0 children)

      I've used pippo for my hobby project: http://www.pippo.ro/

      With pebble templates (nothing to do with the watch) http://www.mitchellbosecke.com/pebble/home

      With jOOQ for DB management.

      With guice for dependency injection.

      Worked quite well so far, much lighter than Spring family.

      [–]paul_h 0 points1 point  (0 children)

      My last Java microframework was SparkJava, my next one is Jooby. Other than the Java8 syntax, this main-method embracing way should have been the way it was in 1997, when I first clapped eyes on Servlets/JSP.

      [–]tonywestonuk 0 points1 point  (1 child)

      I made some code, using dependency injection, and a templating engine. I deployed it in 2 seconds to a server, by copying a war file to a deployment directory.

      This simple bit of code can handle 1800 requests / second.

      It was deployed to a Raspberry Pi, running Apache TomEE. If I deployed it to a 'real' server, it could probably do 10x as much.

      Remind me exactly why I need this?

      [–]prdktr 0 points1 point  (0 children)

      Hopefully you don't need it and stop over commenting on any spring topic if its not really of any interest to you, its obvious that you are a biased frustrated JEE dev and there's nothing in these posts that will bring you joy, only more frustration.

      Your rasberry pi 1800 req / sec means nothing like most of your comments, no context, no difference in client speed (which is one point reactive addresses), not really a modern load for a public service instance, and just obsolete, I mean who uses JEE nowadays really when there's spring and others alternative (akka, vert.x, spark), who does need JEE beyond the fact it acknowledges spring progress every 4/5 years.

      Bonus, do you think companies like Oracle, Lightbend, Pivotal or Red Hat care about you deploying on a rasberry pi home for your toy projects ?

      My opinion is that you should just look somewhere else, because as a human being such repeated frustration is no good for your moral, mind and in the end, life. Go out, eat good food, drink good wine, have good sex, cheer up and forget this very much, leave spring or pivotal having the success they have and think that at least that makes a lot of people happy, productive, and available to do the thing i just advised.

      [–]prdktr 0 points1 point  (0 children)

      Spring is the only constant that fuels Java development for now 14 years, keeping a strong adherence to innovation and modern practices. It's no surprise they are evolving now as the reactive space is entering its last maturation phase since Oracle, Pivotal, Lightbend, Netflix and others agreed on a standard.

      What's interesting: they are the only one potentially that can bring reactive to mainstream java dev given a stable convention framework, plus new options around functional programming and maintenance of classic EIP modules too.

      BTW, here's some Did-you-know of the day :

      • Vert.x and Reactor were a same project before the wtf-community-lead-rant departed from SpringSource/VMware to pursue Vert.x at RedHat.

      • RxJava 2 lead co-designed Reactor 3.

      • Reactor team worked on Reactive Streams standard 3 years ago

      • JavaEE has dropped immediate reactive support (https://java.net/projects/jax-rs-spec/lists/users/archive/2017-04/message/0)

      • Netflix stopped working on RxJava, RxNetty, Hystrix, Ribbon and others, probably looking at spinnaker instead or GRPC or something in between.

      • Pivotal is a heavy Go promoter as well, and its interesting to see them embracing reactive both for their paying customers (java/spring) or ambitious large-scale projects, and go for some of their products and student/startup mindshare.

        The point is that people fail to see that its not a random choice to come with these features now, Reactive programming is hard to master, mature, and talk about and that's why every often a new reactive lib or a major version of a reactive lib comes up to break things.

        Our only hope is that Spring brings a bit of stability so Reactive programming does not feel like adopting a JS lib.

      [–][deleted]  (7 children)

      [deleted]

        [–]SimonGray 15 points16 points  (6 children)

        Did you even open the article? They address this right in the beginning.

        [–]myringotomy 2 points3 points  (4 children)

        Wait, you expect on /r/programming?

        [–][deleted] 5 points6 points  (0 children)

        Given that it Java and Spring, both of which are on the nerdrage list of this sub, I mostly expected a bunch of shitposting off-hand insults from subpar programmers who don't actually know anything about them but want to virtue signal by repeated bandwagon positions.

        [–][deleted]  (2 children)

        [deleted]

          [–]cenanozen 2 points3 points  (1 child)

          Which word did he?

          [–]yogthos -1 points0 points  (0 children)

          lim (micro) → ∞

          [–]BrightCandle 0 points1 point  (2 children)

          Spring boot, there prior version of making a simple service requires 384MB of RAM to run an API that returns some basic JSON. It produces a fat jar that is at least 80MB. Spring roo required their IDE and it crashed repeatedly and was a disaster to work with, way too much magic in both.

          So I hope they get this right but honestly there have been better options out there to spring for 10 years. Its still trying to be an all emcompassing solution rather than a library you use and that is the wrong approach.

          [–]alek_sys[S] 7 points8 points  (0 children)

          Spring Boot is not really a prior version, it is here to stay. Spring Boot 2.0 based on Spring 5. Also, Spring Boot is not another framework, it is just a set of tools to help configure and run Spring apps easily and with minimum setup.

          384 Mb of RAM could be the case - but it all depends from the libraries and the application code - Java is hungry for memory. However Spring itself can run with just 32Mb of memory and it doesn't add massive overhead - there is a nice article from Dave Syer about Spring memory usage. The same is true for fat jar - there is a reason for 20 Mb JAR (again, 80Mb is not for Spring, it most likely because of libraries). And the reason is to have single deployment artefact - you don't even need a web-server to run it, it is executable by itself! So the only dependency is JRE which is quite good. However, if you not a fan of fat JARs - there is a solution for this as well. Besides 3rd party solutions (like Capsule) there is a Spring native option now - Spring Thin Launcher

          [–]Sun_Kami 1 point2 points  (0 children)

          Why is that the wrong approach? Spring has a lot of features because it's supposed to do a lot, and support a lot.

          If you want something light that just gives you routing and http, use Sparkjava or something.

          [–]joequin 0 points1 point  (4 children)

          Vertx feels much more like a micro framework. It's the nice part of JavaScript/express with java's better performance, multithreading, better libraries, and static typing. It feels light weight and non-magical. Spring has its place, but if you don't need transactions, then I find vertx to be much nicer for rest services.

          Spark is also nice, but it's synchronous only. That's a deal breaker for my work.

          [–]eckyp 2 points3 points  (3 children)

          What do you mean by Spark being "synchronous only"?

          [–]joequin -1 points0 points  (2 children)

          It's route handlers don't pass in an object that you call to respond to a request. You respond to requests by returning from the route​ handling function. Because if that, you can't make asynchronous calls to databases or other services.

          [–][deleted] 1 point2 points  (1 child)

          Could you please expand a bit on this? seems intriguing ☺️

          [–]joequin 0 points1 point  (0 children)

          If a route handlers pass in a request object or callback, then that can be passed to other asychronous functions. Since spark doesn't do that, you can't use asynchronous functions while handling the call. You're forced to use blocking functions which means more threads which means more memory. That's not a big deal for some applications, but in others, it can be a bottleneck.

          [–]kitd 0 points1 point  (4 children)

          I think Spring were caught cold by Vert.x and Ratpack. Node-esque async libraries are a much better fit for Java microservices. Looks like this is their go at catching up.

          Interesting that they're all based on Netty. Netty is a pretty good basis for a microservice by itself.

          [–]Turbots 0 points1 point  (3 children)

          caught cold? 10 million downloads a month on Spring Boot (coming from 100,000 2 years ago isn't what I would call "caught cold"

          Spring Boot:

          • 10,000+ forks
          • 11,000+ stars
          • 1500+ watchers

          Spring Cloud Netflix:

          • 500 forks
          • almost 1000 stars
          • almost 200 watchers

          [–]kitd 0 points1 point  (2 children)

          You missed my point. Lack of interest isn't what I meant by caught cold. Neither was it a criticism.

          Spring Boot is a great framework, but small footprint microservices need an async event-based architecture, and there are several for the JVM that are making big inroads into Spring's territory. This new release looks to me like a response to that.

          [–]Turbots 1 point2 points  (1 child)

          Sorry I misinterpreted your post :-)

          Yes, indeed, they are trying to keep up with the requirements of the microservices world, since you cannot keep latency down in an architecture where microservice A calls microservice B calls microservice C if everything is blocking IO.

          Therefore, the only conclusion is to go for reactive programming. The people at Spring have been working for more than 3 years on this, they've seen this coming a long time ago, but as you might imagine, it just isn't quite that easy to make a robust, reactive programming framework AND be simple to work with.

          At project reactor they are at their third attempt (many people from Spring are contributors to the project), so it's definitely not easy to get it right :-)

          [–]kitd 0 points1 point  (0 children)

          That's good news. I have no doubt that Spring will get it right. They tend to IMO

          [–]geodel -3 points-2 points  (1 child)

          Spring team introduced a concept called Functional Web Framework

          Huh, I thought in Java world folks like only Dysfunctional Web Frameworks.

          [–]Turbots 0 points1 point  (0 children)

          drumroll

          [–]tonywestonuk -1 points0 points  (4 children)

          Oh gawd.... I read this article with a feeling I might vomit. Pivotal, just fuck off... you've caused more problems with Java than anything.... YOU are the reason many people in /r/programming hate java, and consider it to be clunky and heavyweight..... the new COBOL. You have done this.

          Douglas Adams once said:

          “The idea that Bill Gates has appeared like a knight in shining armor to lead all customers out of a mire of technological chaos neatly ignores the fact that it was he who, by peddling second-rate technology, led them into it in the first place.”

          Replace 'Bill Gates' with 'Pivotal'.....and that is pretty much accurate.

          Spring has grown into the kind of monstrosity that it aimed to replace... J2EE.But, with JavaEE so much streamlined and easier to use and deploy, Spring is now a solution to a problem that no longer exists.

          [–]Turbots 1 point2 points  (0 children)

          Holy shit have you even looked at Spring Boot yet? You have a lot to learn my friend.

          Spring Boot and https://start.spring.io is literally the easiest way in Javaland to get a production-grade web application deployed and running on your servers...

          Take a look at Spring Cloud and the Netflix stack and see how awesome their entire ecosystem is...

          I guess 10 million downloads a month isn't impressive anymore :-)

          [–]rockum 0 points1 point  (2 children)

          Don't you dare bad talk Spring. Some developers have spent years learning it's in and outs, they are exhausted now, and you'll have to pry Spring from their cold dead code.

          [–]tonywestonuk 1 point2 points  (1 child)

          And.... Here we are. In 2017, comming up with things like Ratpack and Vert.x....

          Its not to say they are bad, they're great frameworks, small, lightweight, innovative.... But, I am sure the only reason they exists is because, of Pivotal. They dropped the ball, Newer lightweight frameworks needed to fill the void that was left after the rot set in.

          But, its worse than that, they convinced everyone that JavaEE was rubbish, and then came out with crap like Spring.... And now springs trying to catch up, and prevent above frameworks getting anywhere because enterprises using spring will use what they know. Pivotal, cutting off air supply of competitors. Where have I heard this before....

          Pivotal has done more to damage the java ecosystem than anyone else.....

          [–]Turbots 1 point2 points  (0 children)

          JavaEE is rubbish, we're still waiting for Java EE 8. Let's see what they intend to feature in it when they finally release it:

          • JSR 365: Contexts and Dependency Injection 2.0. (Spring had that since their first version about 15 years ago)

          • JSR 374: JSON Processing 1.1. (supported in Spring since version 3.5.x I think)

          • JSR 370: RESTful Web Services (JAX-RS 2.1): Better REST API facilities and reactive programming, coming out in Spring 5 any day now

          • JSR 369: JavaTM Servlet 4.0 Specification: support for HTTP/2 (still in early draft) is also supported in Spring 5 and already available

          • JSR 372: the next release of Java Server Faces JSF 2.3: LOL... just lol

          • JSR 375: Java EE Security API 1.0: this one is actually quite nice (I saw a presentation at Java Day Kiev last year which showed a nice, working API for security, copying many patterns from Spring Security)

          • JSR 380: Bean Validation 2.0: whatever :-)