神刀安全网

Simple Everyday Tips for Vaadin Developers — Part 2: Using CDI

This is the second part of a five parts series about tips for Vaadin developers. Here are all the series parts:

  1. Migrating From Vaadin 6 to Vaadin 7
  2. UI abstraction and using Vaadin CDI Add-on
  3. Styling Vaadin components and using Add-ons
  4. Data modeling in Vaadin
  5. Simple use case for Vaadin Grid

2. UI Abstraction and Using Vaadin CDI Add-on

After the migration, everything works great, so it’s a good time to add CDI. I will replace the old CDI add-on with the new official Vaadin CDI add-on.

We start by simply placing the dependency in the pom file:

<dependency>   <groupId>com.vaadin</groupId>   <artifactId>vaadin-cdi</artifactId>   <version>1.0.3</version> </dependency>

Then add CDIUI annotation on top of the main UI:

@CDIUI("") public class CoolStoreApplication extends UI implements ClickListener {

There is no need to keep the old servlet so let’s remove it at all and keep the default one automatically provided by CDI add-on, so remove:

@WebServlet(urlPatterns = "/*", name = "MyUIServlet", asyncSupported = true) @VaadinServletConfiguration(ui = CoolStoreApplication.class, productionMode = false) public static class Servlet extends VaadinServlet {}

The UI class is now a CDI managed bean and we can start to use @Inject annotation in our Vaadin code. Make sure that all services are injected and not initialized inside the UI code:

@Inject private ProductService productService;
@Inject private ShoppingCartService shoppingCartService;

Related commit: Use official CDI add-on and cleanup old dependencies

A closer look at our two main views:

Simple Everyday Tips for Vaadin Developers — Part 2: Using CDI Simple Everyday Tips for Vaadin Developers — Part 2: Using CDI They have unified design, header, content, and buttons area. In other words here is how I look at each view programmatically:

Simple Everyday Tips for Vaadin Developers — Part 2: Using CDI They also share a ClickListener event when the user clicks on any button. That’s why I came up with the idea of abstracting the UI. Basically I created an abstract class AbstractView that implements ClickListener, moved the click listener from the main UI to this class, and changed our views to inherit from it.

Related commit: Abstract and decouple the UI

Now the structure of AbstractView should be, in abstract words, consisting of three sections, and those sections can be defined during child views initialization. Following are some important highlights.

To make it even more flexible, I placed an abstract method that can be defined by the child class:

protected abstract void createLayout(VerticalLayout layout);

It would be obvious to call createLayout from the constructor, but having in mind that we are using CDI and decoupling the views, I created a separate init method to automatically call createLayout after the constructor:

@PostConstruct private void init() {   createLayout(layout); }

The trick here is having in the parent class a forceful call to createLayout, so that you don’t need to place @PostConstruct on top of createLayout when overridden.

This gives a good flexibility to take layout in the child views and add our custom content. Now all we need is to surround createLayout call in init by the header and buttons ares. We can reuse the same trick to define the header text by an abstract method placed in the parent class, and the same for the buttons:

protected abstract String getViewHeader();  protected abstract void createControllerButtons();

Related commit: Generalize the header views and Generalize the buttons area in all views

Our views are now really separated and can be used as independent beans, add annotation for each view:

@UIScoped public class ProductsView extends AbstractView {
@UIScoped public class ShoppingCartView extends AbstractView { 

And inject them in the main UI to be placed in the HorizontalSplitPanel.Replace:

private ProductsView productView = new ProductsView(this); private ShoppingCartView shoppingCartView = new ShoppingCartView(this);

With:

@Inject private ProductsView productView;
@Inject private ShoppingCartView shoppingCartView; 

Related commit: Abstract and decouple the UI

As a final step to make it a nicer CDI demo, let’s make the communication between views happen through events. Absolutely no, events are not scary! CDI makes it very simple; first I started with a very simple event class UpdateShopppingCartEvent that delegates a set of Product, the selected products. In ProdcutsView I injected this class as a javax Event:

@Inject private javax.enterprise.event.Event<UpdateShopppingCartEvent> updateCart; 

Then I simply fire this event with the selected products once the user clicks on the “Add To Cart” button:

updateCart.fire(new UpdateShopppingCartEvent(getSelectedProducts())); 

This way we have a guaranteed decoupling between the views, and they don’t depend on each other.

Related commit: Add events between views and fix methods access

The essential parts are done, migration and usage of CDI. But is it possible to make the UI look a bit better? This is what we will discuss in the next part of this article. Wait for it, next week!

转载本站任何文章请注明:转载至神刀安全网,谢谢神刀安全网 » Simple Everyday Tips for Vaadin Developers — Part 2: Using CDI

分享到:更多 ()

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址