Seiten

Donnerstag, 31. Oktober 2013

Donnerstag, 17. Oktober 2013

The power of the ContextResolver Part I

How to use a ContextResolver? What can you do with this?
Let´s say you have something like the following:
@Inject @DemoLogicContext DemoLogic demologic;
But it depends on the transient context of the application to decide what is the right implementation of the interface DemoLogic.

The implementation DemoLogicB is a normal JavaClass, KotlinDemoLogic is writen in Kotlin. Both implementations are paired with a qualifier and a producer like the following in the picture.

At this point you have n implementations with n qualiefiers and maybe n producer. Or it must be possible to extend the running system with a few more different customer dependent implementations. To write this inside your code with an big if else tree it is not a good style. From the busineslogic point of view the right definition is:
@Inject @DemoLogicContext DemoLogic demologic;

For this you can use the producer methods from cdi. The way is quite easy:
@Produces @DemoLogicContext
public DemoLogic create(){...}
With this you have the entry-point for the final injection point. You can extend the signature of the create method with more attributes. Mostly used is the BeanManager and/or InjectioPoint, but you can use your own classes. For example the ContextResolver.
@Produces @DemoLogicContext
public DemoLogic create(ContextResolver contextResolver){...}
The ContextResolver itself is an interface.. this means you have to use an qualifier to define the producer or implementing class for this interface.
@Produces @DemoLogicContext
public DemoLogic create(@DemoLogicContext ContextResolver contextResolver){...}

Now we have to implement the first class, called DemoContextResolver. The DemoContextResolver will be injected into every producer that must be able to decide something.
public class DemoLogicProducer {
    private @Inject ManagedInstanceCreator creator;

    @Produces @DemoLogicContext
    public DemoLogic create(@New DemoContextResolver contextResolver){
        final Class beanType = DemoLogic.class;
        final AnnotationLiteral annotationLiteral = contextResolver.resolveContext(beanType);
        final DemoLogic demoLogic = creator.getManagedInstance(beanType, annotationLiteral);
        return demoLogic;
    }
}
From this point you are able to decide what will be the implementation to use. For this example I wrote a very simple version, but you can extend this to a tree of deciding ContextResolvers.
public class DemoContextResolver implements ContextResolver {

    @Inject DemoContext demoContext;

    @Override public AnnotationLiteral resolveContext(Class targetClass) {
        if(demoContext.getContextInfo()){
            return new AnnotationLiteral() {};
        } else{
            return new AnnotationLiteral() {};
        }
    }
}
The good thing is, that every module will be usable for itself. You can write jUnit-Tests per implementation. At runtime you can add more implementations. Think about the possibility to change the controller for a GUI in this way ;-) I will show this more in detail in my next blog entry (Part II)

Sonntag, 13. Oktober 2013

Using JavaScript libraries (D3) in Vaadin webapplications

This is a short tutorial on how to use JavaScript libraries with Vaadin.

The library that shall be used is D3, which is a powerful library for creating data-driven diagrams using JavaScript.

To keep it simple the final UI will look like this (see the screenshot at the end of the posting): We have a coordinate system in which we have a circle which can be moved inside that coordinate system. The coordinates can be entered in textfields and applied by clicking a button. Maybe there will be another post with some more meaningful use of D3 inside a Vaadin-Application in the future. But this tutorial aims on how to use JavaScript libraries inside Vaadin applications in general.. so let's start!

We have to create two Java classes: Diagram, DiagramState
And we have to create one JavaScript file: diagram_connector.js

First, let's have a look at the Java classes "Diagram" and "DiagramState". The former extends "AbstractJavaScriptComponent". It is the component that is added to the UI in the end (like a Button or a TextField). The latter extends JavaScriptComponentState and is just needed for the communication between Vaadin and JavaScript (or server and client). Here is the code:

Diagram
@JavaScript({"d3.v3.min.js",
        "diagram_connector.js"})
public class Diagram extends AbstractJavaScriptComponent {

    public void setCoords(final List<Integer> coords) {
        getState().setCoords(coords);
    }

    @Override
    public DiagramState getState() {
        return (DiagramState) super.getState();
    }
}
The @JavaScript annotation lists all JavaScrip files that have to be used. The first one is the D3 Library and the second one is the file that we have to create later. In my case both files are in the same folder in which the Vaadin UI-extending class is (AND I had to copy the files into my war manually, but that's a configuration issue of IntelliJ..).

The setCoords method is used to give the Diagram component a list with the x- and y-coordinates of the position the circle should be moved to. The list is delegated to a corresponding attribute of the DiagramState.

The overriden method getState looks always the same (with exception of the name of the State class, of course).

DiagramState
public class DiagramState extends JavaScriptComponentState {

    private List<Integer> coords;

    public List<Integer> getCoords() {
        return coords;
    }

    public void setCoords(final List<Integer> coords) {
        this.coords = coords;
    }
}
The DiagramState class has an attribute which is a list of integers. It contains the x- and y-coordinates of the position the circle should be moved to (inside the coordinate system) as explained above. The rest is simple getters and setters for that attribute.

Now let's have a look at the JavaScript file we have to create.

diagram_connector.js

window.org_rapidpm_vaadinwithjs_Diagram = function() {
    var diagramElement = this.getElement();
    var diagramFrame = d3.select(diagramElement).append("svg:svg").attr("width", 500).attr("height", 500);
    diagramFrame.append("svg:circle").attr("cx", 250).attr("cy", 250).attr("r", 20).attr("fill", "red");

    this.onStateChange = function() {
        var coords = this.getState().coords;
        d3.selectAll("circle").transition().attr("cx", parseInt(coords[0]));
        d3.selectAll("circle").transition().delay(500).attr("cy", parseInt(coords[1]));
    }
}
The first function assigment must always be done that way. Recognize that you assign a function to window.<fully qualified name of the class which extends AbstractJavaScriptComponent with underscores replacing the dots>.

this.getElement() returns the corresponding DOM element for our diagram. (Think of document.getElementById(<the ID of the Diagram element>)).

The following two lines are D3 related. We "select" our element and append a coordinate system to it with a width and height of 500. Then we insert a circle into that coordinate system at coordinates 250,250 (which is the center), a radius of 20 and a red fill color. For more information on how to use the D3 library in detail have a look at their website. There are some nice tutorials.

The assignment of a function to this.onStateChange is always called when the state of the Diagram changes. This happens if we call the setCoords()-method of our Diagram class. If that is the case we get the coords from the Diagram's state. Recognize that coords (which is an Integer-List in the corresponding Java class) is a number array for JavaScript now. As next we select all circles (right, we only have one in our case). Then we move the circle to the new x- and y-coordinate (x = coords[0], y=coords[1]) via a transition (which simply looks cooler).

That's all the magic. Now at last let's have a look at the main class with the init-method of our UI. We have to TextFields for x and y coordinate, a Button to apply the new coordinates and, of course, our Diagram which we can use as any other component as said above:

VaadinWithJavaScriptComponentsUI

public class VaadinWithJavaScriptComponentsUI extends UI {
    final VerticalLayout layout = new VerticalLayout();   
    final TextField xCoordField = new TextField("X");
    final TextField yCoordField = new TextField("Y");
    final Button button = new Button("move circle");
    final Diagram diagram = new Diagram();
    final List<Integer> coords = new ArrayList<>();

    @Override
    protected void init(VaadinRequest request) {

        configureIntegerField(xCoordField);     //not interesting, just adding converter/validator to the textFields
        configureIntegerField(yCoordField);

        button.addClickListener(new Button.ClickListener() {   //ATTENTION! Here we get the coordinates from the textfields and apply them to our Diagram via calling diagram.setCoords()
            @Override
            public void buttonClick(Button.ClickEvent event) {
                if(xCoordField.isValid() && yCoordField.isValid()){
                    coords.clear();
                    coords.add(Integer.parseInt(xCoordField.getValue()));
                    coords.add(Integer.parseInt(yCoordField.getValue()));
                    diagram.setCoords(coords);
                }
            }
        })
        //now we build the layout.
        layout.setSpacing(true);
        layout.addComponent(xCoordField);
        layout.addComponent(yCoordField);
        layout.addComponent(button);
        layout.addComponent(diagram);     //add the diagram like any other vaadin component, cool!
        setContent(layout);
    }

    private void configureIntegerField(final TextField integerField) {
        integerField.setConverter(Integer.class);
        integerField.addValidator(new IntegerRangeValidator("only integer, 0-500", 0, 500));
        integerField.setRequired(true);
        integerField.setImmediate(true);
    }
}

That's it. Here is a screenshot of the result and some (kind of unspectacular) animated pictures.



sources:

Mittwoch, 9. Oktober 2013

use Kotlin inside JavaFX with CDI

I tried the combination of JavaFX with CDI and injection of Kotlin and it works very well.
First the CDI - managed Callable
Second the TextFieldBindingCallable for the JavaFX-binding
Third the implementation of the DemoLogic Java - Version
changed to Kotlin
The code with the @Inject of DemoLogic isn´t changed inside the class LeftTextFieldBindingCallable and it is running well..

Dienstag, 8. Oktober 2013

complex PropertyBindings

Today I had to deal with different dependent input-fields.
Let´s say you have (only) two TextFields, leftTextField and rightTextField. If you writing something into the left TextField you have to calculate something (Logic A) and write it to the right TextField. If you are writing to the right one you have to calculate something (Logic B) and write it to the left TextField.
This example is quite simple, but if you have to deal with a lot of fields with different deps based on a transient context you have to solve:
- cycles between the different components.
- in this case, the transient context that was changing the logic (here Logic A and Logic B).

First the component called PairedTextField.
Now, how to bind both TextFields to get the result? If you are binding bidirectional you will get a Stackoverflow. To solve this you can do something like the following:
This simple solution is working well. Binding if you need it, unbind after this. Thanks to JavaFX PropertyBinding ;-) Finally we have to deal with the different implementations of the logic-part for every request.
The class Bindings will give you the method createStringBinding(Callable, Property), with this you can create the Bindings (leftTextFieldBinding, rigthTextFieldBinding). What you need now is the implementation of the Callable. If you are doing it in the "normal" way you have to write it like the following
With this solution you are not able to switch the implementation of the attribute "demoLogic". Nicer would be something like
With every request you will get the possibility to change the implementation of DemoLogic. The Producer will decide wich implementation will be used.

Now, putting all together:

The importand parts are:

Mittwoch, 2. Oktober 2013

CDI ButtonCell

The full code and demo jUnit you will find under : BitBucket Repo - RapidPM - Modules - javafx-filtered-tableview 
Please use the release/1.1.1 branch and a commit after 6e440e2 

Today I needed a button inside my TableView. Something needed to be activated, based on some other values in this row. How to do this in a nice, lean and decoupled way? One goal was the possibillity that the definition could be done inside the fxml - file. Let´s start with the basic cdi managed ButtonCell: The main part here is the method setOnAction(): With this we are iterating over a list of ButtonCellActions.
Now we have to implement a class for our used TableView. In this example an simple delete-button.
At this point we are able to inject all the needed logic (here :DeleteButtonLogic) to fullfill our task. The logic will be activated inside an implementtion of the class ButtonCellAction. The order you are filling the Actions is the order the actions are processed. quite easy and mostly all you need.
The implementation is easy, but we want to put this to an fxml file like the following?: For this we need the CellFactory and the CellValueFactory. Both implementations are small: This is all.. and the result is nice and clean..