We have created a large application based on GWT (and SmartGWT). The more the application has grown the longer it takes to start the dev mode or to refresh a page in the browser.
I have read a lot of posts in the web about this problem, like e.g. this one:
However currently it takes almost 10 minutes to startup the enitre setup and beeing able to do some tests. A refresh takes about 2-3 minutes. This is more than slow or in other words in-acceptable The benefit of GWT is maintenance of large applications and except for this problem it does a perfect job. The GWT developers have really done an excellent job in hiding the browser hell from the java programmer. Thanks!
So what are we doing wrong. First of all some details about our architecture:
1. We are using GWTP and therefore GIN. While I personally think that the MVP approach is more academic as if something changes in a dialog you have to both change presenter and view so the separation of these two with interfaces etc. is often more in the way than a real help. However, GWTP does a great job for history management (back button, bookmarking dialog state), for composition of dialogs using slots and for code-splitting. With this learning we only use presenters for the main dialogs but do not use GWTP for subdialogs but created our own layer for that. However for > 100 dialoges all presenter proxies need to be rebound. However each of them is very fast. In total ~15 seconds.
2. We are using GWT-RPC and we have ~100 Services. As the actual approach of GWT with Async-Interfaces was not suitable for this scale from our point of view. From Google I/O I heard of a great concept of having a single generic RPC service that can adopt any logical service. I have reimplemnted this as Open-Source-Project if someone whats to understand this in detail:
The main idea is to have a marker interface for services and use a rebinding generator to generate a stub for each service that collects the arguments and puts them in a serializable object. This approach also allows bundling multiple service calls in one physical HTTP request with 1-2 lines of code.
In our large project we already did some optimizations to avoid having Serializable as type of the service arguments. Still rebinding for this already takes one minute.
3. We are using SmartGWT. I do not like this decision for arbitrary reasons but however it has really great widgets where plain GWT is way to low level.
4. We need a way to show our business objects received in the client in list grids. Due to a strange design of SmartGWT and the lack of reflection in GWT this was not so easy. We solved this with another rebinding generator that automatically converts our business objects into the required structure of SmartGWT (ListGridRecord). However rebinding of this again takes ~30 more seconds.
5. We are using the i18n messages feature of GWT. As we have a modular system build out of 7 subsystems we have 14 *Messages (one for errors and one for texts) interfaces that need to be rebound. Another ~8 seconds.
6. We also use springframework and have a set of server side components that take another 10-15 seconds to startup. We already have a separate tomcat with all the persistence logic so our GWT client is a separate webapp with a serverside that only delegates to the tomcat backend. This already speeds up development and doing changes in the backend is fast and smooth.
The total amount of delay appears to be a large sum of multiple pieces. I still need to investigate and analyze in more detail.
It already takes a minute before I get the launch URL
The most extreme thing is however when I open the URL in the browser and have to wait a long time until I get something like this:
[TRACE] [portal] - Found 6727 cached units. Used 6727 / 6741 units from cache.
Often it says Found 0 cached units. Then I have to wait 1-2 Minutes until the next trace log message appears.
***
My main question is simple: Why is there no way to tell GWT to reuse rebinding results, etc. instead of doing everything from scratch all the time?
Of course one could remove all code from the entry point and put a totally different client inside so the behavior is fine as default. But if I change a single line of code
and need to refresh the current dialog to test this change, why the heck do I need the CompilingClassLoader to regenerate my entire application from scratch.
I digged into GWT and found that there is a CLI option -XenableGeneratorResultCaching what seems to be what I am looking for. However I failed in using it properly
or it is not completely implemented as it appeared to me from digging into GeneratorExtWrapper. I also patched this class with no luck...
Is there anybody who can give me a hint with this? Are there any new features in 2.5 that could help me or something planned for future releases?
A little optimization I could add is creating a development dialog that allows to reset all views so if a dialog is reopened the view is recreated. This helps for changes that get hot-synced by GWT. However most changes are not and require a fresh start of GWT dev mode (10 minutes).
Ideally I would also need a way to prevent regeneration after fresh start.
Maybe I have to kick out all GWT-Generators and replace them with real java code generator that are invoked only when the input changes.
Any hints to speed up the development time is very welcome.
Cheers
Jörg