ExtJS is a very powerful JS framework, which comes with the most complete set of UI widgets out-of-the-box of any framework I've seen. There are also links with GWT, in the form of GXT (produced by the same company as the main framework), and Ext-GWT which was the original link, and continues as a result of the debate over the ExtJS licencing change moving from LGPL to GPL.
For our application, we've used the plain JS library, and written it as a single-page AJAX application (i.e. the browser only ever loads /index.html), along with our own JS classes to wrap up the business functionality, primarily panel-by-panel. More information on general ExtJS design principles can be found here. Specifically I would recommend a read of the Big Application, and Extending classes before you dive straight in, but there are many other good tutorials on the site.
DWR allows Java beans to be exposed straight to an HTML page as a Javascript object. At first glance, this sounds dangerous, but it's actually quite safe is a few precautions are taken. The developers of DWR have clearly thought about the security implications of such a framework, and you can easily protect yourself:
- Create an interface on your service bean, which only has the methods designed to be called from the UI. This is good practice anyway, but also prevents any accidental exposure of public methods on your service you didn't intend to expose.
- DWR forces you to name/mark all the beans you intend to serialize over to the JS object, including the ability to work with generics, or explicitly specify the collection types if not available.
- DWR works with Hibernate loaded objects, and specifically proxies, so that while you have to pre-load any lazy-loaded associations, it will only expose those associations that have actually been loaded. This saves both network bandwidth, and also information leakage if you don't actually want parts of the domain model exposed to the client.
- Used in conjunction with Spring, use Spring Security (formerly Acegi) to wrap authorization around the various service methods to ensure that only users authorized to call them can.
Hibernate is still used as a persistence layer. In particular, with its support for externalised named queries, we can have our DAOs (or a base class) expose a query(String, Map<String, Object>) method, saving us bothering to put a new method for each and every query we want to allow, while only allowing the queries we want to. If you need to, you can also use Hibernate filtering to further restrict the queries at runtime based on the authenticated User for instance.
The Service can also provide a similar query(String, Map<String, Object>) which can delegate straight to the DAO (Careful! You will need to whitelist the named queries you actually need the UI to execute if there are other queries defined on your Hibernate session factory that you wouldn't want run ....)
This allows the UI (via DWR) to make Service.query(queryName, namedParameterMap) calls straight from the JS without having to implement individual query methods in the various components. All our data loaded into the UI is done via this mechanism, primarily so that we can mark everything as lazy-loading, and then use queries, along with the "fetch join" for each use-case to only load the data required for that particular user action.
Spring is used to tie all of these technologies together, configure all the various parts such as Hibernate and DWR. All the requests go through a Spring DispatcherServlet, which also allows us to link in the DWR controller and service URLs with some very small Spring MVC usage for index.html and a few admin/test pages.
Hopefully more (probably non AJAX) posts to follow without such a gap :D
No comments:
Post a Comment