Grails vs Spring performance for REST - java

I've created some REST endpoints using pure Groovy/Grails. For now most of the operations are all CRUD-like.
I'm beginning to compare the performance of the Grails app to an equivalent Java/Spring app for the CRUD scenarios that I've made, using JMeter. So now I'm taking a subset of the scenarios I've implemented in Grails and porting to a basic Spring MVC app.
I'm very interested in seeing performance comparisons published by others on the web. Can anyone refer me to some?
Any other information in regards to the testing and analysis I'm going to do is welcome. Thanks!
UPDATE REGARDING THE ANSWER:
#Lari's answer below references a website with extremely comprehensive tests, comparing Grails 2.X vs Spring 4.X (see README.md), in addition to a multitude of other frameworks.
However, those tests have Grails running on Resin while Spring is on Tomcat. A little strange to me since Grails uses Tomcat by default.
Resin and Tomcat arguably have similar performance.
The website has several sections (tabs on top) and even subsections (tabs in the "Results" area). My original question was regarding web service behavior for REST. To that end here are the top-level sections that answered my question:
Querying multiple rows in a DB table (HTTP GET) and returning JSON array as result.
Modifying multiple rows in a DB table and returning JSON array as result. This test does not use HTTP PUT with a body, but instead HTTP GET. Scroll to bottom of page for details, and also Requirements page.
If you're interested in HTML rendering see the Fortune Cookie example.
Not surprisingly Spring is better, but like #Joshua points out, this is a contrived example and you will have to be the judge of what to extrapolate from the results. Not to mention that Grails used Resin while Spring used Tomcat. Hopefully each server (Tomcat / Resin) was configured similarly in terms of max threads, Java memory, etc? The config files may be buried in the source code (if you find out, let me know).
I also setup dummy applications for Spring 4.X vs Grails 2.X, with Tomcat being configured exactly the same (both used the same standalone Tomcat installation rather than one bundled inside Grails). In my tests I performed an HTTP GET and returned a JSON array which was formed using static (pre-instantiated) in-memory objects (no DB query). My results also showed better performance for Spring (sorry I can't find my data any longer!). I used Spring Boot to slap a Spring app together quickly, and Grails already has scaffolding by default.

There is http://www.techempower.com/benchmarks/ . The source code is at github.

Take a look at this PLAY VS. GRAILS SMACKDOWN presentation. You can find some results of perfomance inside.

Related

What are the disadvantages of using spring boot in production? [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 4 years ago.
Improve this question
Spring boot is not adopted in our organisation.
The disadvantages cited are bloated jars, less control and flexibility.
I have tried to investigate above points but so far they dont seem valid.
bloated jars - The spring blog states that a simple web server
can be launched with 10 MB of heap.
less control and flexibility - Netflix uses spring
boot.Moreover,when I did some poc's, I didnt face flexibility issues.
I wanted to know if there are any mistakes in assesment.
1)Any examples on the loss of control/flexibility will be helpfull.
2)What are the anti patterns we need to be aware so the bloated jars issue dosent happen.
It is often a question of concern and responsability. With Spring boot, the developper team has full control of the deployed environment, including the servlet container configuration. And the production team has nothing to tweak.
Without Spring boot, the developper team has only control over the web application. And the production can/has to tweak the servlet container configuration. When you have a large number of different web apps, it can make sense to let the knowledge on that part only in the production team. In that case, you would not use Spring boot.
On the other end, if the hosting is externalized, Spring boot allows to give a full package.
So both approaches can be used but they target different organizations.
Bloated Jars - I think this can be fixed by properly maintaining the jars using a build tool like maven (But, yes there are some instances where you may need to add a lot of jars just because spring needs it)
Less control and flexiblity - I think this is usually with control freaks who want to control each and every piece of code they write. If you are okay with what spring provides already, this shouldn't be an issue.
I believe that the biggest disadvantage that you might encounter using spring is using it without understanding what value it might add to your project.
It might be completely not aligned with your requirements and it is possible that you will configure everything by yourself at some point, when you think, you should not have started with spring itself.
Ask your self a few questions,
You can create standalone java application? Why Spring at the first place? What value it adds to your project?
Spring has embedded tomcat, jetty, so no need to build a war. But, what if you have to build war anyway? Little config will do the trick but it's not any major advantage. Also, when you start it as a java service, what happens to your service if somehow the java process got killed?
What if you have many legacy spring modules? What if you need to patch it up? This will increase the jar count as well as legacy classes count. Are you sure want to convert this into a spring-boot application?
What if spring autoconfig configuration is not aligning with your requirements
And, I myself used spring-boot for a few of our production applications, which are mostly standalone REST API services and, haven't faced any issues with it.
Some best practices will be,
Use spring-boot mostly for microservices instead of a single complete (MVC) web application (I always use it to build the standalone REST API and build the UI with ReactJS and NodeJS).
Build your spring-boot app as a docker image and deploy using some kubernates cluster (kubernates will take care of failed docker containers and deploying to new containers) for maximum uptime.
Always keep only the jars required by your project and remove unwanted jars.
Any examples on the loss of control/flexibility will be helpfull.
You need familiarity on the life cycle of a bean in a Spring Boot application. Not knowing this might hinder your experience in spring boot. This will force you to structure your beans to prevent circular dependencies and other problems.
In Spring Security, configuring your other login methods is not really that intuitive.
In Spring Data JPA, repo classes requires you to name the methods in a specific way to perform queries. Locking/releasing data rows is also not straightforward.
etc...
What are the anti patterns we need to be aware so the bloated jars issue dosent happen.
Review the dependency tree of your jars. Make sure to add dependencies only in the modules they are needed. Also, remove dependencies you don't need.

Microservices - Stubbing/Mocking

I am developing a product using microservices and am running into a bit of an issue. In order to do any work, I need to have all 9 services running on my local development environment. I am using Cloud Foundry to run the applications, but when running locally I am just running the Spring Boot Jars themselves. Is there anyway to setup a more lightweight environment so that I don't need everything running? Ideally, I would only like to have the service I am currently working on to have to be real.
I believe this is a matter of your testing strategy. If you have a lot of micro-services in your system, it is not wise to always perform end-to-end testing at development time -- it costs you productivity and the set up is usually complex (like what you observed).
You should really think about what is the thing you wanna test. Within one service, it is usually good to decouple core logic and the integration points with other services. Ideally, you should be able to write simple unit tests for your core logic. If you wanna test integration points with other services, use mock library (a quick google search shows this to be promising http://spring.io/blog/2007/01/15/unit-testing-with-stubs-and-mocks/)
If you don't have already, I would highly recommend to set up a separate staging area with all micro-services running. You should perform all your end-to-end testing there, before deploying to production.
This post from Martin Fowler has a more comprehensive take on micro-service testing stratey:
https://martinfowler.com/articles/microservice-testing
It boils down to a test technique that you use. Here my recent answer in another topic that you could find useful https://stackoverflow.com/a/44486519/2328781.
In general, I think that Wiremock is a good choice because of the following reasons:
It has out-of-the-box support by Spring Boot
It has out-of-the-box support by Spring Cloud Contract, which gives a possibility to use a very powerful technique called Consumer Driven Contracts.
It has a recording feature. Setup your Wiremock as a proxy and make requests through it. This will generate stubs for you automatically based on your requests and responses.
There are multiple tools out there that let you create mocked versions of your microservices.
When I encountered this exact problem myself I decided to create my own tool which is tailored for microservice testing. The goal is to never have to run all microservices at once, only the one that you are working on.
You can read more about the tool and how to use it to mock microservices here: https://mocki.io/mock-api-microservices. If you only want to run them locally, it is possible using the open source CLI tool
It can be solved if your microservices allow passing metadata along with requests.
Good microservice architecture should use central service discovery, also every service should be able to take metadata map along with request payload. Known fields of this map can be somehow interpreted and modified by the service then passed to next service.
Most popular usage of per-request metadata is request tracing (i.e. collecting tree of nodes used to process this request and timings for every node) but it also can be used to tell entire system which nodes to use
Thus plan is
register your local node in dev environment service discovery
send request to entry node of your system along with metadata telling everyone to use your local service instance instead of default one
metadata will propagate and your local node will be called by dev environment, then local node will pass processed results back to dev env
Alternatively:
use code generation for inter-service communication to reduce risk of failing because of mistakes in RPC code
resort to integration tests, mocking all client apis for microservice under development
fully automate deployment of your system to your local machine. You will possibly need to run nodes with reduced memory (which is generally OK as memory is commonly consumed only under load) or buy more RAM.
An approach would be to use / deploy an app which maps paths / urls to json response files. I personally haven't used it but I believe http://wiremock.org/ might help you
For java microservices, you should try Stybby4j. This will mock the json responses of other microservices using Stubby server. If you feel that mocking is not enough to map all the features of your microservices, you should setup a local docker environment to deploy the dependent microservices.

Reverse engineering a java rest based services from database

Problem
I have a relational database schema (in Oracle, but could be in Mysql or Postgres) and I need to expose basic CRUD operations on tables with REST services, all withtout a line of code from a developer.
Constraint of my problems are: java 6/7 only (not scala, groovy, etc..), maven based solution, possibly framework agnostic (could be separated from Spring, for example).
A mandatory requirement is all of this stuff must run on Tomcat (6 or 7).
Bonus: junit of similar automated test on CRUD operation using Mocks and a webpage to test services
Possible solutions
I have already investigated into Spring Roo, not finding a decent configuration or tutorial for my problem.
I have tried to reverse-engineering database using jboss hibernate tools and fits well. Using this tool I can manage to do a maven module (a persistence jar) with all entities mapped.
But I also need a code organization using DAO pattern (to handle entities) and a service layer (to setup REST services).. and this seems to be tricky.
Edit: I've found this solution, using maven hbm2dao, I'm on right path?
Thanks for your time!
p.s: I've found this solution, seems good, but is made with python :(

Integrating grails into an existing spring application?

What if you don't want to start a separate project for grails but instead sneak it into an existing webapp?
I have to build an admin interface/crud for some new entities and thought it would be a perfect way to learn grails.
I'm trying to make one application with a Grails app and a Spring app.
I've tried to sneak the Grails App into the Spring one, but this is "impossible". It's easier to sneak the Spring app into the Grails app. Grails knows what Spring is, but Spring has no idea of what Grails is.
In this article you can find useful information about how to use your hibernate mapping files or annotations in Grails, so you don't have to remap everything. Also you can use all your java clases (put them into src/java). You can put the beans defined in the ApplicationContext.xml in conf/spring/resources.xml. You can leave them in ApplicationContext, but I've had some problems.
I don't have ended the job (almost) and it looks good.
It would be hard to "sneak it in" unless the existing app has the correct dir structure that maps exactly to how grails likes it - after all, convention over config is where the power of grails comes from.
You can try doing the admin interface as a "seperate" app to the original/existing spring app, and map the existing database to the grails domain objects. though i m not sure how you would run them side by side easily without more information on the existing app. It is possible definitely though.
I agree that building your admin interface is a good exercise to learn Grails, and also agree with the previous answer that Grails is difficult if not impossible to integrate with an existing Spring application. You could probably get it done, but the headache would not be worth it.
Grails is built on top of Hibernate for its ORM, so if you're already using Hibernate with this Spring app you can work this to your advantage. It's not too difficult to configure a Grails app to use pre-existing Hibernate models, and this is explained well in Grails documentation.
So, I'd recommend building up your admin console as an independent Grails app but make use of the Hibernate models you already have, if in fact you've used Hibernate.

What's the best way to share business object instances between Java web apps using JBoss and Spring?

We currently have a web application loading a Spring application context which instantiates a stack of business objects, DAO objects and Hibernate. We would like to share this stack with another web application, to avoid having multiple instances of the same objects.
We have looked into several approaches; exposing the objects using JMX or JNDI, or using EJB3.
The different approaches all have their issues, and we are looking for a lightweight method.
Any suggestions on how to solve this?
Edit: I have received comments requesting me to elaborate a bit, so here goes:
The main problem we want to solve is that we want to have only one instance of Hibernate. This is due to problems with invalidation of Hibernate's 2nd level cache when running several client applications working with the same datasource. Also, the business/DAO/Hibernate stack is growing rather large, so not duplicating it just makes more sense.
First, we tried to look at how the business layer alone could be exposed to other web apps, and Spring offers JMX wrapping at the price of a tiny amount of XML. However, we were unable to bind the JMX entities to the JNDI tree, so we couldn't lookup the objects from the web apps.
Then we tried binding the business layer directly to JNDI. Although Spring didn't offer any method for this, using JNDITemplate to bind them was also trivial. But this led to several new problems: 1) Security manager denies access to RMI classloader, so the client failed once we tried to invoke methods on the JNDI resource. 2) Once the security issues were resolved, JBoss threw IllegalArgumentException: object is not an instance of declaring class. A bit of reading reveals that we need stub implementations for the JNDI resources, but this seems like a lot of hassle (perhaps Spring can help us?)
We haven't looked too much into EJB yet, but after the first two tries I'm wondering if what we're trying to achieve is at all possible.
To sum up what we're trying to achieve: One JBoss instance, several web apps utilizing one stack of business objects on top of DAO layer and Hibernate.
Best regards,
Nils
Are the web applications deployed on the same server?
I can't speak for Spring, but it is straightforward to move your business logic in to the EJB tier using Session Beans.
The application organization is straight forward. The Logic goes in to Session Beans, and these Session Beans are bundled within a single jar as an Java EE artifact with a ejb-jar.xml file (in EJB3, this will likely be practically empty).
Then bundle you Entity classes in to a seperate jar file.
Next, you will build each web app in to their own WAR file.
Finally, all of the jars and the wars are bundled in to a Java EE EAR, with the associated application.xml file (again, this will likely be quite minimal, simply enumerating the jars in the EAR).
This EAR is deployed wholesale to the app server.
Each WAR is effectively independent -- their own sessions, there own context paths, etc. But they share the common EJB back end, so you have only a single 2nd level cache.
You also use local references and calling semantic to talk to the EJBs since they're in the same server. No need for remote calls here.
I think this solves quite well the issue you're having, and its is quite straightforward in Java EE 5 with EJB 3.
Also, you can still use Spring for much of your work, as I understand, but I'm not a Spring person so I can not speak to the details.
What about spring parentContext?
Check out this article:
http://springtips.blogspot.com/2007/06/using-shared-parent-application-context.html
Terracotta might be a good fit here (disclosure: I am a developer for Terracotta). Terracotta transparently clusters Java objects at the JVM level, and integrates with both Spring and Hibernate. It is free and open source.
As you said, the problem of more than one client web app using an L2 cache is keeping those caches in synch. With Terracotta you can cluster a single Hibernate L2 cache. Each client node works with it's copy of that clustered cache, and Terracotta keeps it in synch. This link explains more.
As for your business objects, you can use Terracotta's Spring integration to cluster your beans - each web app can share clustered bean instances, and Terracotta keeps the clustered state in synch transparently.
Actually, if you want a lightweight solution and don't need transactions or clustering just use Spring support for RMI. It allows to expose Spring beans remotely using simple annotations in the latest versions. See http://static.springframework.org/spring/docs/2.0.x/reference/remoting.html.
You should take a look at the Terracotta Reference Web Application - Examinator. It has most of the components you are looking for - it's got Hibernate, JPA, and Spring with a MySQL backend.
It's been pre-tuned to scale up to 16 nodes, 20k concurrent users.
Check it out here: http://reference.terracotta.org/examinator
Thank you for your answers so far. We're still not quite there, but we have tried a few things now and see things more clearly. Here's a short update:
The solution which appears to be the most viable is EJB. However, this will require some amount of changes in our code, so we're not going to fully implement that solution right now. I'm almost surprised that we haven't been able to find some Spring feature to help us out here.
We have also tried the JNDI route, which ends with the need for stubs for all shared interfaces. This feels like a lot of hassle, considering that everything is on the same server anyway.
Yesterday, we had a small break through with JMX. Although JMX is definately not meant for this kind of use, we have proven that it can be done - with no code changes and a minimal amount of XML (a big Thank You to Spring for MBeanExporter and MBeanProxyFactoryBean). The major drawbacks to this method are performance and the fact that our domain classes must be shared through JBoss' server/lib folder. I.e., we have to remove some dependencies from our WARs and move them to server/lib, else we get ClassCastException when the business layer returns objects from our own domain model. I fully understand why this happens, but it is not ideal for what we're trying to achieve.
I thought it was time for a little update, because what appears to be the best solution will take some time to implement. I'll post our findings here once we've done that job.
Spring does have an integration point that might be of interest to you: EJB 3 injection nterceptor. This enables you to access spring beans from EJBs.
I'm not really sure what you are trying to solve; at the end of the day each jvm will either have replicated instances of the objects, or stubs representing objects existing on another (logical) server.
You could, setup a third 'business logic' server that has a remote api which your two web apps could call. The typical solution is to use EJB, but I think spring has remoting options built into its stack.
The other option is to use some form of shared cache architecture... which will synchronize object changes between the servers, but you still have two sets of instances.
Take a look at JBossCache. It allows you to easily share/replicate maps of data between mulitple JVM instances (same box or different). It is easy to use and has lots of wire level protocol options (TCP, UDP Multicast, etc.).

Categories

Resources