Seiten

Freitag, 27. Dezember 2013

Developing leJOS programs with IntelliJ on Windows

LeJOS is the java library which is needed to develop and run java programs on Lego Mindstorms robots. Four days ago, the newest alpha version 0.5.0 was released. One big new feature is an all new gui-menu which is displayed on the LCD-Display for executing programs on the brick without executing a remote command (via telnet or SSH).

The official guides use eclipse as the IDE for developing lejos programs and in this tutorial I want to explain how to develop programs with IntelliJ on Windows. I will also show how to transfer finished programs to the brick and execute it via remote connection and via the new display menu.

Initial situation


You have created the bootable MicroSD-Card for running Lejos (version 0.5.0-alpha) on the Mindstorms brick and inserted it into the brick (a tutorial on how to create is can be found here. Recognize that the procedure has changed from version 0.4.0-alpha to 0.5.0-alpha). You also have a compatible WiFi-Stick (e.g. Netgear WNA1100) which is inserted into the USB-Plug on the brick.

So let's start. What we will do is:
  1. Clone the official lejos git repository to get the sources which we need to build our program
  2. Create and configure the IntelliJ-Project for our lejos program
  3. Write the code for the program (the usual HelloWorld from the official guide)
  4. Create a runnable JAR-File of the program
  5. Transfer the JAR-File onto the brick via WiFi / SSH
  6. Execute the program via the new display menu
  7. Alternative way of executing the program: Execute the program via WiFi / SSH (the old-fashioned pre-0.5.0-way)

1 Clone the official lejos git repository to get the sources which we need to build our program

For cloning the lejos git repository you must have installed git (which can be obtained from here). For comfort (not having to use single git commands on the command line) we used the free-to-use (for non-commercial use) GUI-Tool SmartGitHg 5 (version 5.0.5) by syntevo which rocks and can be downloaded on the official site. When you start the program for the first time you have to tell SmartGitHg where your git installation is located, but thats quite straight-forward and the wizard will help you doing that. After you have started and configured SmartGitHg choose:
"Project" --> "Clone ..."
Then choose:
"Remote Git, Mercurial or Subversion Repository" and enter git://git.code.sf.net/p/lejos/ev3 into the textfield.
Then click "Next". In the next window make sure both check boxes are checked. Click "Next" again. Choose a path where the source should be copied to (We chose the path "F:\projects\ev3-sources" which we will call EV3-SOURCES by now). Then click "Next" again. On the last window choose the option "Open in new project" and leave the name in the textfield as it is. Finally press "Finish". SmartGitHg will then start downloading all files from the repository. This might need some minutes. You can watch the progress in the right bottom corner of the window.
After the download has finished the window should look like the following:

SmartGitHg, downloaded EV3-sources



At last we have to choose the 0.5.0-alpha tag branch. Choose "Branch" --> "Checkout...". In the following window choose the 0.5.0-alpha tag branch as shown in the following picture:

checking out the 0.5.0-alpha tag branch
Press "Check out" and then choose "Check out commit without switching to a branch".

Now that we have the lejos sources in version 0.5.0-alpha let's start creating our IntelliJ project for our HelloWorld-Program.

2 Create and configure the IntelliJ-Project for our lejos program

Start IntelliJ and choose: "File" --> "New Project...". Choose "Java Module" and call it HelloWorld. We saved it in "F:\projects\HelloWorld" (which I will call HELLOWORLD by now). Then press "Next" and "Finish".

Now that we have a raw new project, lets first configure it before creating the HelloWorld-code. Open the project settings ("File"-->"Project Structure") and click on "modules". Then click on "Add Content Root" and choose EV3-SOURCES\ev3-classes\src and click on "OK". Do the same with EV3-SOURCES\DBusJava\src.
As next click on "Librarys" on the "Project Structure"-window. Click on the green "+" and choose "Java". Then choose the folder EV3-SOURCES\ev3-classes\lib and click on "OK". Click on "OK" again.
Press "Apply" and "OK" to close the project structure window now.
Your project structure should now look like this:

Project structure

3 Write the code for the program

Now let's create the code. Create a class in HelloWorld\src and call it "Main". Make it look like the following:

import lejos.hardware.Button;
import lejos.hardware.lcd.LCD;

public class Main {
    public static void main(String[] args) {
        LCD.clear();
        LCD.drawString("First EV3 Program", 0, 5);
        Button.waitForAnyPress();
        LCD.clear();
        LCD.refresh();

    }
}
 
If the imports fail, something went wrong with the configuration of the project structure.

As you can see the class implements the Main-method. It will show "First EV3 Program" on the display of your EV3-Brick until you press any button on the brick.

That's it. Now we are ready to create a runnable JAR of our program.

4 Create a runnable JAR-File of the program

Open the project settings again ("File" --> "Project Structure..."). Click on "Artifacts".Click on the green "+" and choose "Jar" --> "From modules with dependencies...". Leave everything as it is in the new window but enter "Main" into the field "Main Class" like in the following picture:

Creating jar-file
Then click on "OK". Click on "Apply" and close the Project Structure-Window. Now we need to do one last thing before creating our ready-to-execute Jar. There is a new folder in your HelloWorld-src folder called "META-INF". It contains a MANIFEST.MF-File. It contains two lines as you can see in the following picture:

MANIFEST-file




Now you need to add the following line:
Class-Path: /home/root/lejos/lib/ev3classes.jar /home/root/lejos/libjna/usr/share/java/jna.jar

You can copy/paste that line because the paths are absolute paths on the MicroSD-card.

That's it. Save everything and choose "Build"-->"Build artifacts..."-->HelloWorld.jar-->"build". If you get some warnings that's okay. If you get errors anything went wrong (let us know). Now we have created a Jar-File (in HELLOWORLD\out\artifacts\HelloWorld_jar) which we can transfer via WiFi to the EV3-Brick.

5 Transfer the JAR-File onto the brick via WiFi / SSH

To transfer the jar-file from our workstation to the EV3-Brick we need a connection to it. So start your EV3 with the lejos-MicroSD-card and the WiFi-Stick inserted. Make sure that your robot has an IP-Adress in your network. A description on how this is done via the menu can be found here (that didn't work for us, so we had to edit the file /etc/wpa_supplicant.conf on the microSD-card by hand).

Now that our EV3 is online and connected to the WiFi we will transfer the jar-file onto the robot. Therefore we need to download pscp.exe from http://www.chiark.greenend.org.uk/~sgtatham/putty/download.html. We downloaded it to "C:\Users\Marco\Downloads".
Open up a cmd-box (Windows-Button --> enter "cmd", then choose cmd.exe) and navigate to the folder which contains the downloaded pscp.exe. Then enter the following command:


pscp -scp HELLOWORLD\out\artifacts\HelloWorld_jar\HelloWorld.jar root@IP_OF_EV3:/home/lejos/programs


If you are asked for the root password just hit enter. The root user on the linux-system on the microSD card has no password. In my case that looked like the following:

transfering the jar-file onto the brick
That's it! The file now was copied onto the EV3-brick (in /home/lejos/programs). Time to execute our program.



6 Execute the program via the new display menu

On the display menu move to "Files" (by pressing the right button). Press "Enter" (the middle button). Now you will see "HelloWorld.jar" on the display. Press "Enter" again. Now you will see "Execute Program" on the display. Press "Enter" once more and enjoy the magic :). It will need some seconds where you will only see a blank display. But then the "First EV3 Program" will be displayed as expected. When you press any button the program will end as expected and you will be back at the menu. Congratulations for running your lejos program developed with IntelliJ on Windows!

7 Alternative way of executing the program: Execute the program via WiFi / SSH (the old-fashioned pre-0.5.0-way)

Sometimes you might want to run your programs which you uploaded onto the brick remotely instead of pressing buttons on the brick. One solution for this is to use a ssh connection via putty. So  download it from http://www.chiark.greenend.org.uk/~sgtatham/putty/download.html (putty.exe). After downloading, execute the putty.exe. Enter the IP of your EV3 into the field "Host Name (or IP address)" and click on "Open". This will open a remote console. Enter "root" as user name and just press enter when asked for password. Now you could run your program. But we have to do one more thing before executing the program: We have to disable the menu. If we wouldn't do this, both (the String "First EV3 Program" of our program AND the display menu) would be displayed in the display. So in the menu navigate to "System" and select "Suspend Menu". The menu will now be suspended and the display will be blank. Now back to our remote console. Enter the following command to execute the program (which we transfered to /home/lejos/programs on the brick earlier):
jrun -cp /home/lejos/programs/HelloWorld.jar Main
remote console in putty

Look at the display and enjoy the magic again ;). It will again need some seconds until you will see the string on the display. Hit any button on the brick to end the program. If you want the menu back after executing the program press the middle button and the lower button on the brick. The display menu will be back instantly.

If you have any questions or problems during the process feel free to leave a comment.

Dienstag, 24. Dezember 2013

Happy Holiday from RapidPM

Hey Folks,

we at RapidPM (humans as well as non-humans) wish you a happy holiday season and a happy new year 2014. May it be successful in every way for you and us. We would also like to thank you all for your interest in our blog and our projects and we hope you will keep visiting us in 2014 :-)


Montag, 16. Dezember 2013

Our new project: Lego® Mindstorms® M1ndSuite

*drum roll*..............Voila! Today we officially announce our new project called M1ndSuite. It will be developed parallel to our cdi-commons project.

What is it / What is it going to be?

In general: MindSuite (or "M1ndSuite") will be a gui- (web-)application for controlling and/or monitoring Lego® Mindstorms® robots.

For those, who don't know what Lego® Mindstorms® is: The official website says:
LEGO® MINDSTORMS® EV3 has arrived! Combining the versatility of the LEGO building system with the most advanced technology we’ve ever developed, unleash the creative powers of the new LEGO MINDSTORMS EV3 set to create and command Robots that walk, talk, think and do anything you can imagine. Follow the step-by-step 3D building instructions to create TRACK3R, R3PTAR, SPIK3R, EV3RSTORM and GRIPP3R and bring them to life with an easy, intuitive and icon-based programming interface.
Sounds cool, doesn't it?

Image what you could create with all those possilities! Or look what others already did :-D

  

But let's come back to our planned MindSuite application. At this juncture we can't tell what will be the definite features because we first have to become acquainted with the whole subject. But possible features might be:
  • offering pre-built programs for different robots
  • possibility to create new (persistent) programs for any robot (like with the official Lego software) and real-time transfer of these into the robot's operating system
  • real-time monitoring of the robot's sensors / motors / ...
  • real-time control for the robot (e.g. "move forward/backward", "turn left/right", "play sound xyz" ...)
We can imagine plenty of features, but (as already said) at this early moment we first have to get deeper into the topic. Our Mindstorm hardware just arrived on friday and we have just done our first experiments (we have built the Lego Mindstorm robot Gripp3r and loaded the standard Lego programs for it onto the EV3 brick so we could remote control it with the infrared remote control).

What frameworks will be used?

Well, of course nothing is certain at this moment (we don't even have certain features xD) but chances are good that the (web-)application will use the spring framework.
There is already a java API for creating programs for the robots called LeJOS (http://www.lejos.org/). We're pretty sure that we will use that to realize the communication between the MindSuite and the robots.

Why are we doing this?

Everyone is talking about the topics M2M (Machine-to-Machine) / IoT (Internet of Things) at the moment. We are very excited about these topics, too! And we love the idea behind Lego Mindstorms with all its possibilities! So creating a new software for controlling and monitoring those robots seems to be the perfect chance for us to get into that stuff. We can't wait to get started!

As always with our projects, MindSuite will be open source and its code will be hosted on bitbucket. You will find the code at https://bitbucket.org/rapidpm/m1ndsuite, but at this moment you won't find anything there of course. Give us some weeks ( or months? :) )..we don't have a roadmap yet. But we will regularly post updates on our blog to keep you informed of the current state, be curious! :D

first logo concept
we already built one of the Lego Mindstorms (Gripp3r)

Montag, 9. Dezember 2013

Adam Bien´s afterburner.fx internals explained..

Today I am writing about Adam´s framework afterburner.fx. This is a MVP framework for dependency injection into JavaFX apps. It is very small, containing only two classes.

What could you do with this afternburner.fx? What are the restrictions?

Let´s start with the project init. You will need only a normal pom.xml, plain no special libs are needed. I am using JDK8 because of the simple JavaFX config. (no config ;-) )

Convention over Configuration:
CoC is the main in this framework. This means, that you don´t need to configure something. But you have to follow the base structure that this framework is expecting.

As app-base-pkg I am using org.rapidpm.demo.jaxenter.blog008. (you could get all from my git repo under https://bitbucket.org/rapidpm/jaxenter.de-0008-afterburner ) The main class will be Main, this is the JavaFX Application Class with the basic boostrapping intro. The sup-pkg orig contains the pkg presentation with only one GUI module called demo. For every GUI Module you will need two classes. The first one is a class with a name ending with View and the second one will end with Presenter. In our examplke you will find the two classes, DemoView and DemoPresenter.

The DemoPresenter is nothing else as the Controller class for the View, declared inside the fxml file.
The fxml File itself must be named demo.fxml and at the same place as the Presenter/Controller class.

 The DemoView is the GUI Component itself and must extend the FXMLView class from the framework.

The View - FXMView 
The DemoView have a default constructor, calling the init method. init(Class clazz, String conventionalName) 


public FXMLView() {
    this.init(getClass(), getFXMLName());
}

private void init(Class clazz, String conventionalName) {
    final URL resource = clazz.getResource(conventionalName);
    String bundleName = getBundleName();
    ResourceBundle bundle = getResourceBundle(bundleName);
    this.loader = new FXMLLoader(resource, bundle);
    this.loader.setControllerFactory(new Callback, Object>() {
        @Override
        public Object call(Class p) {
            return InjectionProvider.instantiatePresenter(p);
        }
    });
    try {
        loader.load();
    } catch (Exception ex) {
        throw new IllegalStateException("Cannot load " 
            + conventionalName, ex);
    }
}
The init will load the ResourceBundle and the fxml-file with an instance of the class FXMLLoader. The most importand step is the setting of the ControllerFactory. Inside the instance of the ControllerFactory you will see the methodcall InjectionProvider.instantiatePresenter(p);  This ist the place where the injection will be taken place. One big point to know is, only inside a controller/presenter you will be able to use injection. Inside the Presenter no injection is available.

The InjectionProvider - DI with reflection
The InjectionProvider ist the heart of the framework. The base steps are the following:
- create an instance
- inject the attributes with the annotation Inject
- call the method with annotation Postconstruct
Thats all... but how it is realized?

The first step is quite easy, just call clazz.newInstance().

Step two is a littele bit more complex. You have to instantiate the attributes but the the attributes inside too. Thes means the injection must be done recursive. To do this you will check the attributes if they are annotated with Inject, if so, do the same for this instance.. and so on..
There is a small thig to know. The implementation from Adam will only create one instance of every used class. This means you will get only singletons!! And this for the complete application.

The last step is easy again, call all methods with the annotation Postconstruct per reflection.

static Object instantiateModel(Class clazz) {
    Object product = models.get(clazz);
    if (product == null) {
        try {
            product = injectAndInitialize(clazz.newInstance());
            models.put(clazz, product);
        } catch (InstantiationException | IllegalAccessException ex) {
            throw new IllegalStateException(
                "Cannot instantiate view: " + clazz, ex);
        }
    }
    return product;
}

static Object injectAndInitialize(Object product) {
    injectMembers(product);
    initialize(product);
    return product;
}

static void injectMembers(final Object instance) {
    Class aClass = instance.getClass();
    Field[] fields = aClass.getDeclaredFields();
    for (final Field field : fields) {
        if (field.isAnnotationPresent(Inject.class)) {
            Class type = field.getType();
            final Object target = instantiateModel(type);
            AccessController.doPrivileged(new PrivilegedAction() {
                @Override
                public Object run() {
                    boolean wasAccessible = field.isAccessible();
                    try {
                        field.setAccessible(true);
                        field.set(instance, target);
                        return null; // return nothing...
                    } catch (IllegalArgumentException | 
                                IllegalAccessException ex) {
                        throw new IllegalStateException(
                            "Cannot set field: " + field, ex);
                    } finally {
                        field.setAccessible(wasAccessible);
                    }
                }
            });
        }
    }
}
static void initialize(Object instance) {
    invokeMethodWithAnnotation(instance, PostConstruct.class);
}
Lesson Learned
The framework afterburner.fx from Adam Bien is really small without any configuration. You could use this to inject Instances per annotation Inject. If you want to use this inside your application you have to know the following:


  • There are no Scopes, all instances will have the the lifecycle of the application. The only way to terminate them earlier is to call the method forgettAll(), but this will terminate all instances. The method annotated with PreDestroy will be called before. You could not select the order the instances are destroyed.
  • All instances are singletons
  • No Producers, this means you could not abstract over an Interface layer. Or you can not switch between different implementations like you could do with Qualifiers.
If you could deal with this limitations, this will be good form you. But to use this to learn more about injection works, this is a good project to play with.






Montag, 18. November 2013

Vaadin with CDI

Todays post will show a mini tutorial on how to use CDI with the current Vaadin version (7.1.8). To keep it simple, I will just extend the official Vaadin-HelloWorld-Program a bit.

The normal Non-CDI-HelloWorld-Program works like that: There is a "Click Me"-Button on the screen and when you click that button, a label with the text "Thanks for clicking" is added below that button.
I will extend that HelloWorld-Program by using (injecting) our RapidPM-CDILogger which prints a WARN-Message on the console ("Button was clicked").

The project structure looks like the following:



I created that Vaadin-project via Maven (see https://vaadin.com/download).

To get the program working, we have to make the following changes:
  1. Add the Vaadin-CDI-support and the RapidPM-Modules as dependencies in the pom.xml
  2. Create a log4j.properties in the resources-folder to configure the logger
  3. Modify the Vaadin UI-Class (called MyVaadinUI per default)
That's all. So let's start:

1)
Add the following dependency entries to the pom.xml:

<dependency>
      <groupId>com.vaadin</groupId>
      <artifactId>vaadin-cdi</artifactId>
      <version>1.0.0.alpha1</version>
</dependency> 
<dependency>
       <groupId>org.rapidpm.modul</groupId>
       <artifactId>cdi-commons</artifactId>
       <version>1.2-SNAPSHOT</version>
       <scope>compile</scope>
       <type>jar</type>
</dependency> 

The first dependency is needed to get Vaadin working with CDI, the second is needed to use our RapidPM-Logger.
Attention: The logger won't work with cdi-commons in version 1.1.1

2)
Create a file called log4j.properties:

log4j.rootLogger=DEBUG,stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - %m%n

That file is needed for log4j, which is used by our CDILogger. Put it into src/main/resources. I had to create that resources-folder and mark it as a source-folder manually.

3)
Modify the MyVaadinUI-Class so it looks like the following:
import com.vaadin.annotations.Theme;
import com.vaadin.annotations.VaadinServletConfiguration;
import com.vaadin.cdi.CDIUI;
import com.vaadin.server.VaadinRequest;
import com.vaadin.server.VaadinServlet;
import com.vaadin.ui.Button;
import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.Label;
import com.vaadin.ui.UI;
import com.vaadin.ui.VerticalLayout;
import org.rapidpm.demo.cdi.commons.logger.CDILogger;
import org.rapidpm.module.se.commons.logger.Logger;

import javax.inject.Inject;
import javax.servlet.annotation.WebServlet;

@Theme("mytheme")
@SuppressWarnings("serial")
@CDIUI
public class MyVaadinUI extends UI
{

    /*
    @WebServlet(value = "/*", asyncSupported = true)
    @VaadinServletConfiguration(productionMode = false, ui = MyVaadinUI.class, widgetset = "VaadinWithCDI.AppWidgetSet")
    public static class Servlet extends VaadinServlet {
    }
    */

    @Inject
    @CDILogger
    private Logger logger;

    @Override
    protected void init(VaadinRequest request) {
        final VerticalLayout layout = new VerticalLayout();
        final Button button = new Button("Click Me");
        button.addClickListener(new Button.ClickListener() {
            public void buttonClick(ClickEvent event) {
                layout.addComponent(new Label("Thank you for clicking"));
                logger.warn("Button was clicked");
            }
        });
        configureLayout(layout, button); //Only configuring layouting-issues
    }

    private void configureLayout(final VerticalLayout layout, final Button button) {
        layout.setMargin(true);
        layout.setWidth("100%");
        layout.addComponent(button);
        setContent(layout);
    }
}
Explanation:
- The @CDIUI Annotation at line 19 is needed to make the project use CDI.
- Recognize that the inner class at lines 24-27 must be commented out (you can delete those lines completely, of course). If this isn't commented out the Logger is not injected properly and a NullPointerException is thrown when calling methods of it.
- The CDILogger is injected in lines 30-32
- When the button is clicked, a label is added to the layout and a WARN-message is posted on the console via our logger (lines 40/41).

-----------------------------

The result looks like the following:

links:
Vaadin-CDI-integration

Samstag, 9. November 2013

SpeedUp from Charts with Streams

Today we I am writing about the possibillity to speedup the JavaFX GUI elements with the new streams-API from JDK8.
Let´s play with the original example from Oracle. The LineChart demo will be used as base for the following. We are collecting/generating values for a line of points for every hundreds step. Al steps between are interpolated with splines. For calculating the splines I am using the jakarta-commons math3 lib. [1]
Normaly the following steps are needed to generate a LineChart. - get the base values to show
- calculate the interpolated values
- create the line-elements
- fill the Line-Chart and show it

Get the base values to show
For this example we are generating the values we are needing. To hold the values for a List of curves I am using a Without streams you could do it like this:
But with streams I could write this in a more compact form. The nice here is the possibility to concat the single steps. But this is only to show the new streams api. There is no parallel part. Calculate the interpolated values Now I will start to caclculate the interpolated values. For this I am using the commons-math3 lib from Apache. The way to do this is short and straid forward. - Get the base values from the curve you want to calculate on
- Choose the algorithm you want to use
- Fill the base values as init into the function
Now we are able to caculate the interpolated values. This is something we can do in parallel for every curve. This means that we can start with the speed up. The importand parts are the ".parallelStream()" to start a Thread for eveery elements of the List and during the "map(v-> ... )" phase the calculation is done. Every task is put to the Root - Fork-And-Join Pool. Create the line-elements The grafical elements for the Line-Chart are created in the same way. In parallel for every curve. Fill the Line-Chart and show it Now the last step is the filling of the Line-Chart itself. This is done in a seriel way. No parralel way is possible in the moment. But this is not the part that could bring a speed-up. Lesson Learned What we can see is the possibillity to speed up the GUI part in several ways. Not only the generating of the values itself. The creation of the grafical elements could be done in parralel too. The seriell Version LineChartSerialDemo, needed for the 11´th round 2.799.209.417ns and the parralel version LineChartDemo was done in 261.545.220ns. This is a speed up of 10 at my MacBookPro. Happy coding..

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..

Dienstag, 24. September 2013

Java 9 and GPU?

http://m.heise.de/developer/meldung/JavaOne-GPU-Beschleunigung-mit-Java-9-1964814.html

Donnerstag, 19. September 2013

CDI Callback<TableColumn, TableCell> cellFactory - from FXML

How to get a full managed JavaFX-element declared in the fxml-file?
Let´s say we have something like the following:
This looks like a normal definition of a TableView with some cell-factories. The intressting part is the instantiating of the cellFactory elements. They are created from the JavaFX part. How to get them as full managed bean?
Based on my blog entry about (CDI-JavaFX bootstrapping) I wanted to have full cdi managed JavaFX elements but defined in my fxml-file.
How to get this with a ComboBoxCell you can see here (cdi comboboxcell how to reduce 80 of code)
The aproach was to define an element that is able to associate itself as CellFactory. Only two line of code are used during the init - phase:
BUT: the definition inside the fxml-file is
You only could (implicit)define a normal CellFactory, because the creation of this element would be done by JavaFX.
Now I want to write a more precise fxml file.
Now you could see, the CellFactory is well defined. Here an EditingAutoCompleteStringCellFactory. This is an element with injected autocomplete functions/data.
Inside this class you can use all cdi features.
The missing part is: How to get this as managed instance?
The short answer is.. make it managed by yourself ;-)
Let´s say the controller is a managed instance, you can get the BeanManager with
Now I started to get during the init-phase the right column
After you found the right column, start with the CDI-stuff Ready.. but this code is not nice... and done for every column this is toooooo much code.
So I started to reduce it.
- reducing the generics..
- getting the class from the instance itself
Done.. OK, this is short and easy.. and you can do it for every column..
or more generic...
Now you can use CDI-managed elements as CellFactories and define them inside your fxml.
Nice, Managed and TypeSave

Mittwoch, 11. September 2013

11 lines of code for optimal col size (TableView)

To combine the property tableMenuButtonVisible="true" from the TableView with the column.prefWidthProperty() you need not more than 11 lines of code. The result will be a TableView with automatic resizing columns if you are hiding one ore more columns and reverse.





Dienstag, 10. September 2013

FullText - SearchBox for TableView Part I

How to combine a FullTextSearch with a TableView?
I would say, you will need 30 min max ;-) But How?
Short version :

  • implementing 2 small methods
  • put a SearchBox element to the fxml file
  • combine the TableView with the SearchBox 

Long version:
Let´s start with the correspondings jUnit.

As described (here) we will start with a small demo - jUnit, containing a TableView.
To make the example smaller I will use a default TableView.

The full code and demo jUnit you will find under : BitBucket Repo - RapidPM - Modules - javafx-searchbox 
Please use  a commit after 59237d3

The application based on the SearchBoxDemoPane
with the SearchBoxDemoPaneController.

and the transient data for the TableView TransientDemoDataRow
The importand part is the implementation of the Interface SearchBoxDataElement, this will make the connection between the index and the full-text search later.


Now we will put the SearchBox to the fxml.
This is only one line 
 <SearchBox fx:id="SearchBox" visible="true" minHeight="24.00" prefWidth="1024.0" maxWidth="-Infinity"/>

Finally we are implementing the jUnit Test (more info about cdi javaFX bootstraping)
like this one.

After this we have a full funktional combination between a full-text SearchBox and a TableView.
The SearchBox itself is working in this version with a transient Lucene-Index.









Where to find the cdi-commons and javafx modules ?

Since RapidPM-Modules is available at the central repo (Thanks SonarType), we are using the following repositories.

For development: (no stable builds/ development branch ci )

For Releases and Snapshots from the release-branches/master-branch

Freitag, 6. September 2013

CDI - ComboBoxCell - How to reduce 80% of code

The full code and demo jUnit you will find under : BitBucket Repo - RapidPM - Modules - javafx-filtered-tableview 
Please use the develop branch and a commit after aec4f95 


Today I had a TableView with the following function.
- In one column there was a ComboBoxCell.
- The values of this ComboBox was calculated / loaded at the moment the combobox was used.
- Each ComboBox will have different values based on the context of this row.

The first version was something like this:
A ComboBoxCell:
and the code called from the controller:

This is to much boilerplate code. So I started to reduce it.

First step was reducing the generics..
This is shorter, but not better... 

The solution is the abstract GenericComboBoxCell. (part of the javafx-filtered-tableview module)

Iterating over the columns are now part of the GenericComboBoxCell, and here will be the typesave code.

The developer must extend this class and has to implement the following methods only:
- protected abstract GenericComboBoxCell getComboBoxCellRef(); 
- public abstract boolean disableComboBox(final RT row); (optional) 
- public abstract List createComboBoxValues(final RT row); 
- public abstract void workOnRowItself(final RT row); (optional) 

A demo implementation is shown here: 

The controlle will need a piece of code like this: 

With this you can test the context logic indepentend from the javafx stuff. 
All initializations inside a ComboBoxCell must be done in a PostConstruct - method. 

With the GenericComboBoxCell you can activate/deactivate the combobox, modify the row cell values, and create the combobox values. 

This implementation is based on the JavaFX/CDI bootstrap from cdi-commons-fx. (blog entry JavaFX/CDI bootstrap )






UML of this demo:



Full CDI dependicies