Discussions

News: Groovin' with WebWork 2: Using Groovy as Actions

  1. Where do dynamic languages such as Groovy fit into our Java world? Christian Parker has found a niche, using Groovy as the language of choice for his WebWork 2 actions. In this article he discusses how he added support for Groovy in WebWork, and how he has a nice dev environment where he can simply change the .groovy action, and hit reload on his browser to see the changes!

    Read Christian Parker in Groovin' with WebWork 2

    Threaded Messages (20)

  2. Where do dynamic languages such as Groovy fit into our Java world? Christian Parker has found a niche, using Groovy as the language of choice for his WebWork 2 actions. In this article he discusses how he added support for Groovy in WebWork, and how he has a nice dev environment where he can simply change the .groovy action, and hit reload on his browser to see the changes!Read Christian Parker in Groovin' with WebWork 2
    What is meant by 'dynamic language'? What is a 'scripting language'?
  3. How does it perform compared to standard actions?
  4. How does it perform compared to standard actions?
    I haven't pounded it with any performance tests yet. The way it's implemented uses a really simple cache. Each time the action is invoked the timestamp of the .groovy is compared against the timestamp of the cached class built from the .groovy. So if the .groovy hasn't changed there would be a little time hit to check the timestamp of the file but that's all.

    CP
  5. Each time the action is invoked the timestamp of the .groovy is compared against the timestamp of the cached class built from the .groovy.
    Why do not do the same with Java classes in a specialized classloader?
    At least when I write plain Java code I have available full power of modern IDEs: syntax checking, code-complete, refactoring and all other goodies.
  6. I would certainly check the performance. I did an informal evaluation of Groovy vs. Janino for class generation and was pretty disappointed with Groovy. With what should have been the same generated class for each, groovy's class was almost twice as slow as Janino's class; and this was a _simple_ class mind you. I feel that the 'issue' is the use of the ASM library, but I cannot confirm this completely.

    You can see my results at: http://jroller.com/page/sftarch

    - Robert
  7. ASM is used to generate byte code, but it is generated only once and this is very trivial 'issue' if generation is twice slow.
  8. It isn't the generation of the ASM code that is slow, it is the *execution* of it that was slower. The tests I conducted did not take into account the generation of the byte code itself, but merely just the execution of it. One would think there wouldn't be much difference between two compilers/generators generating a simple one method class, but I guess there is.

    - Robert
  9. One would think there wouldn't be much difference between two compilers/generators generating a simple one method class, but I guess there is.- Robert
    If you look at Groovy generated bytecode, you can see why. The major difference that I saw was is that every method call is done by reflection. It is that way because Java is static typed and use primitives, while Groovy is dynamically typed. Groovy has to always use objects, while methods it calls might be using primivites, and it's not known at compile time. Thus the method call cannot use the bytecodes invokevirtual, invokestatic, etc., it has to use reflection, send objects such as Integer, and have the reflection API convert them to primitive if needed.
  10. Ahh, I had not thought of that and I didn't bother to dig deeply into why groovy ran the way it did. I suppose for things like primitives they could do some autoboxing-like routine, but I doubt it is high on the priority list. I did however take a look at how the GroovyObject.invoke method operated (as I tried that approach as well), and it does essentially the same thing that the BeanUtils does, use reflection and cache where possible. However that approach was still many times slower than even BeanUtils.

    Oh well, I'm sure they will tune it down the road.
  11. New Article for An Old Idea[ Go to top ]

    Using scripting languages for actions has been around for quite a while. It was part of JPublish back in 2001. The only thing different is the language, in this case Groovy. As someone who has been developing webapps for quite some time using scripting languages for the actions I would like to share a couple of thoughts based on my experiences.

    First, performance will probably be an issue, especially as traffic increases. In my case I have used both Jython and BeanShell and both have performance problems which become much more evident as the number of requests per minute increases. In the case of BeanShell I am able to take the code and convert parts of it to Java as necessary. You can do the same to Groovy code too, it seems, as long as you are coding in Groovy so that it is similar to Java. Once you start to use some of Groovy's more "non-Java" syntactical features then the conversion will be much more complicated (this is actually the primary reason I switched from Jython to BeanShell).

    Next, there is the potential for brain damage to occur when switching between languages. Once again this is less of a problem if the scripting language is close to Java, however it becomes a big problem when the language is very different. And before you say "Well, I have no problem switching" keep in mind that a.) you probably won't be the only one touching the code and b.) you most likely will leave while the code will remain in use and thus someone else will have to take over.

    Finally when you develop with scripts it is much easier to develop with cut & paste. It is important to be aware when you do this and to be prepared to refactor as necessary to move shared code into real Java classes. It may seem obvious for me to say this but it is very easy to forget.

    Sincerely,
    Anthony Eden
  12. groovyc[ Go to top ]

    Luckily with Groovy you can groovyc your scripts down to .class files.

    If you decompile them you will potentially see "Groovy stuff" (as in extends GroovyObject... etc).

    In my experience the performance hit is then minimal as:

    1) Your actions should be doing minimal work
    2) Compared to talking to the DB etc it is insignificant

    Dion
  13. jythonc[ Go to top ]

    same goes for jython

    http://www.jython.org/docs/jythonc.html
  14. performance[ Go to top ]

    In my experience the performance hit is then minimal as:
    1) Your actions should be doing minimal work
    2) Compared to talking to the DB etc it is insignificant
    Dion
    1) Even if they're doing minimal work, it's still the point where every request goes through, so when the number of requests grows and you want to keep the ms to the minimum it still can pose an issue. But of course it depends on the amount of requests you're expecting to handle....
    2) For big traffic sites, usually a second level cache is used (at least for page-view-read-only requests), so it can happen that you're building your pages fully from the cache, not touching the DB. And so, at that time scale, a few miliseconds can still be important.

    Fernando
  15. performance[ Go to top ]

    2) For big traffic sites, usually a second level cache is used (at least for page-view-read-only requests), so it can happen that you're building your pages fully from the cache, not touching the DB. And so, at that time scale, a few miliseconds can still be important.Fernando
    Content cache is the best way for this stuff, it can be very "transparent"
    ( Filter ) it is good idea to store "prepared" bytes in cache to avoid encoding convertions. You will get better response time with this cache than for static content and it will not need to execute any actions if page is cached, synchronization in cache will have some overhead, so you need very clever hash map or B-Tree implementation, B-Tree must be the most scalable way in this case .

    The most trivial way to implement this kind of cache is to store output in cache from "GET" and to invalidate all pages on "POST" (it asumes "GET" is readonly, "POST" always writes someting), but it is possible to optimize with different filter mappings or to parse URL's and execute custom actions to invalidate cache.

     "SEND IF MODIFIED" is the next good optimization, it is the best way for static content, but it can be used in the same way as content cache, but store content on client .
  16. performance[ Go to top ]

    You will get better response time with this cache than for static content and it will not need to execute any actions if page is cached, synchronization in cache will have some overhead, so you need very clever hash map or B-Tree implementation, B-Tree must be the most scalable way in this case . The most trivial way to implement this kind of cache is to store output in cache from "GET" and to invalidate all pages on "POST" (it asumes "GET" is readonly, "POST" always writes someting), but it is possible to optimize with different filter mappings or to parse URL's and execute custom actions to invalidate cache. "SEND IF MODIFIED" is the next good optimization, it is the best way for static content, but it can be used in the same way as content cache, but store content on client .
    When number of pages in a site is a degree of magnitude bigger than the number of bussiness object instances (think imdb, or any navigational forum tool), I think it will make more sense to cache the bussiness objects. With pluggable Hibernate Cache, there are a couple of options.
    I guess this is now the appropriate moment for Cameron Purdy's product ad...:-)
  17. performance[ Go to top ]

    Content cache works for web sites like this (TSS).
    How many posts you see in this site per day ?
     50 - 100 transactions per day.
    Are pages very "large" ?
     30 - 50 kb. html per page.

    This site must work on single PC without problems.
  18. Just because many of the dynamic languages can be (or in the end, just are) compiled to .class files, that does not imply they will have the performance characteristics of compiled java code. All the bells and whistles that get added to the dynamic languages to make them dynamic can add a few layers of cake to the runtime story. Not saying they do, but they can. Look at the .java source output of jythonc as an example of the type of overhead that can occur.
  19. ...and how he has a nice dev environment where he can simply change the .groovy action, and hit reload on his browser to see the changes
    I'm getting the same behaviour for changing .java files using Eclipse Hotswap......
  20. I also had idea to use groovy together with webWorks2. But instead of using it for actions I thought it would make much more sense to use it for View's, groovlets instead of JSP or Velocity. And there maybe is yet another possible use for groovy, it's to use it instead of OGNL.

    At the end every groovy script can be compiled (not sure but it seems it always is compiled) to Java bytecode ( .class file). So performance benefit should be positive.

    Remis
  21. reloadable groovy actions?[ Go to top ]

    I don't see the java language as being that bad for WW actions. I don't really see what using groovy gives you - I think most of the hard work is really in the views. Webwork has had reloadable java actions for quite a while now...