Sonntag, 8. Oktober 2017

Java 9 with JavaFX for Raspberry PI

After fiddling around with OpenJDK and OpenJFX I was finally able to run a simple JavaFX application on my Raspberry PI again.

Beware: This "distribution" is not fully tested. I even had to disable any JavaFX test normally running during the build process. Use at your own risk!

I've bundled it into three tar.gz files:

* All in one (jre, jdk, jmods, gengraphs, sec-bin.zip - openjdk-jfx-9_linux-arm6hf.tar.gz)
* Just the JDK (openjdk-jfx-9_linux-arm6hf-jdk.tar.gz)
* Just the JRE (openjdk-jfx-9_linux-arm6hf-jre.tar.gz)

Google-Drive Link:

java.version reports 9-internal

Known Issues

* If you have screen blanking turned on, JavaFX will not reactivate the screen on any touch event. Once I figured out how to do this in code, I'll try to add that functionality.


Build-Process Details 


You will also find a file called build_for_raspberry.patch with all the changes I had to apply to the build script - and even to some native source files.

My changes are split into two areas:

1) The build process itself.
e.g. I had to add some --add-exports to make the compiler happy. This might be due to the fact that I used a vanilla OpenJDK 9 without any JavaFX already integrated and thus all the required exports were missing.
I also had to disable all tests!

2) Changes to some native files. Something I totally do not understand! No clue! So incredible.
I hade a name clash between
modules/javafx.graphics/src/main/native-glass/gtk/GlassApplication.cpp
and
modules/javafx.graphics/src/main/native-glass/gtk/launcher.c
The functions
Java_com_sun_glass_ui_gtk_GtkApplication__1queryLibrary
and
JNI_OnLoad
were duplicate. I chose what I think is the best match and commented in the other file.

Further JavaFX failed to initialize the 7"-LCD correctly and was not able to set e.g. the cursor.
I had to add a line initialize the bcm host.
Affected file: modules/javafx.graphics/src/main/native-glass/monocle/dispman/DispmanCursor.c  

Last but not least
modules/javafx.graphics/src/main/native-prism-es2/monocle/MonocleGLFactory.c
referenced an include missing from the distribution.

Samstag, 11. Oktober 2014

JavaFX - finally there


For our inhouse application I once wrote a framework to make it easier to deal with all the things you have to keep in mind when developing a Swing application.
I ended with a custom binding mechanism which took care of all the threading stuff and it was quite easy to develop an application that way.
Then, JavaFX grew and it was very clear that this will become the new Java UI standard with tons of new possibilities.
But, like Swing you have to take care of things like an UI thread which should not block but must be used to update the UI.
Thanks to my framework I were able to completely convert my Swing app to JavaFX - yes, 100% JavaFX now - in light speed.

As with Swing, there is no standard JavaFX desktop application framework.
But something like this might come:

So, I wonder if my framework can be a part of this effort.
I think, the way how I bind the UI element to the model is very interesting.

A controller looks like a simple Java class using normal properties.
Lets call this a "model controller":



What JavaFX calls controller than, is for me just a description of how to bind the view to the controller.
Lets call this a "view controller":




In this "view controller" then there is a method which describes how the data of the model is bound to the UI control:


Notice how I bind a nested model property (the postalAddress) to the UI control.
AND - all this without string constants.

Using Java 8 method references to bind actions:

The data transfer between the model and the UI control happens in an request/response fashion. Means, it is not updated automatically and immediately, but, before one issues an action, the data is copied form the view to the model and afterwards it is copied back from the model to the view.

Yep, one can easily notice that I came from JSF. Theoretically my "model controller" can be used unmodified to serve the data even for JSF applications!

Well, one might ask - what is this "ServiceCenterController.p." stuff? This is how I think properties have to work in Java. I found the idea to this somewhere in the Internet yeas ago. Unhappily I can't find it just yet to link to the original blog post.

It comes down to a static class structure which describes the properties. I wrote an IntelliJ Plugin to automate this process.



The only drawback here is, that I still can not deal with recursive models. The initialize of the FirstClass structure will end as some depth.

The last bit to wire things up is the @PropertyChangeSupport annotation which is used by an Java agent to, yep, implement a special java.beans.PropertyChangeSupport which also provides javafx.beans.ObservableValues.
The use of the Java agent might be problematic for embedded devices not using a JVM (RoboVM).

... so, I wonder, if some of you find this useful and if I should try to Open-Source my framework.

What do you think?

Freitag, 22. Juli 2011

Java properties

Today, I once again complaint about the missing of first-class properties in java. A long term wish a lot of people would like to see fixed. Beside first-class methods (really?) and Closures for sure.

Today, I once again searched the internet about the current state of this wish.
And, once again, I saw that nothing happened ... really nothing?

No, I came across the term "abstract enum" and how one would like to represent Java properties with this extension to java. [1]
I were excited immediately, just to see, that an "abstract enum" is not possible with Java yet, and that this is also a long term wish someone would like to see.

*rant-on* Seems like Java is a big hive of "long-term-wishes" *rant-off*

Nevertheless, I wanted to see how it feels to have properties like that.

I started with two simple classes
public class PropBean
{
    public static enum p
    {
        propA, propB, propC, propD
    }

    private String propA = "pA";

    private String propB = "pB";

    private String propC = "pC";

    private String propD = "pD";

    public String getPropA()
    {
        return "f" + propA;
    }

    public void setPropA(String propA)
    {
        this.propA = propA;
    }

    public String getPropB()
    {
        return "f" + propB;
    }

    public void setPropB(String propB)
    {
        this.propB = propB;
    }
}

public class PropBean2 extends PropBean
{
    private String propD = "YY";

    public String getPropA()
    {
        return "XX";
    }
}

Not much magic, but as you can see, the PropBean class declares an enum (p) with all the fields we would like to expose as (kind of) "first-class" properties.

Now, with a modified (compileable with the current Java version) PropertyDefinition class (as outlined in the blog [1]) I am able to do the following:

public static void main(String[] args)
    {
        PropBean2 bean = new PropBean2();

        System.err.println(property(PropBean2.p.propA).get(bean));
        System.err.println(property(PropBean2.p.propB).get(bean));
        System.err.println(property(PropBean2.p.propC).get(bean));
        System.err.println(property(PropBean2.p.propD).get(bean));
    }

and the output will be

XX
fpB
pC
YY

Now, THAT is not that bad I think. Good enough for a "poor-man's-property". Sure the enumeration is not combile-time-safe against refactorings, but yay, this is something I can not fix. Probably one can create an IDE plugin (IntelliJ IDEA please!) to automagically populate this enum!?

And, sure, this thing is not able to deal with PropertyChangeSupport, for this I use AspectJ already - curious? ;-)


Here we go with the completely undocumented PropertyDefinition class - just in case one would like to start experimenting too.

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class PropertyDefinition
{
    private final static Map<Enum, PropertyDefinition> propertyDefinitions = new ConcurrentHashMap<Enum, PropertyDefinition>();

    private final Map<Class, PropertyDefinitionAccessor> accessors = new ConcurrentHashMap<Class, PropertyDefinitionAccessor>();

    private final Class modelClass;

    private final String fieldName;
    private final String propName;

    private PropertyDefinition(Enum en)
    {
        modelClass = en.getDeclaringClass().getEnclosingClass();
        fieldName = en.name();
        propName = Character.toUpperCase(fieldName.charAt(0)) + fieldName.substring(1);
    }

    public Object get(Object obj)
    {
        PropertyDefinitionAccessor accessor = getAccessor(obj);

        return accessor.get(obj);
    }

    private PropertyDefinitionAccessor getAccessor(Object obj)
    {
        Class clazz = obj.getClass();
        PropertyDefinitionAccessor accessor = accessors.get(clazz);
        if (accessor == null)
        {
            accessor = new PropertyDefinitionAccessor(clazz);
            accessors.put(clazz, accessor);
        }
        return accessor;
    }

    public void set(Object obj, Object value)
    {
        PropertyDefinitionAccessor accessor = getAccessor(obj);

        accessor.set(obj, value);
    }

    private class PropertyDefinitionAccessor
    {
        private final Class modelClass;
        private final String getterMethodName;
        private final String setterMethodName;
        private Field reflectField;
        private Method getterMethod;
        private Method setterMethod;

        public PropertyDefinitionAccessor(Class clazz)
        {
            this.modelClass = clazz;

            this.getterMethodName = "get" + propName;
            this.setterMethodName = "set" + propName;

            try
            {
                this.reflectField = modelClass.getDeclaredField(fieldName);
                this.reflectField.setAccessible(true);
            }
            catch (NoSuchFieldException e)
            {
                try
                {
                    this.reflectField = PropertyDefinition.this.modelClass.getDeclaredField(fieldName);
                    this.reflectField.setAccessible(true);
                }
                catch (NoSuchFieldException e2)
                {
                    throw new RuntimeException(e);
                }
            }

            try
            {
                this.getterMethod = modelClass.getDeclaredMethod(this.getterMethodName);
            }
            catch (NoSuchMethodException e)
            {
                try
                {
                    this.getterMethod = PropertyDefinition.this.modelClass.getDeclaredMethod(this.getterMethodName);
                }
                catch (NoSuchMethodException e2)
                {
                    // nothing overloaded
                }
            }

            try
            {
                this.setterMethod = modelClass.getDeclaredMethod(this.setterMethodName, this.reflectField.getType());
            }
            catch (NoSuchMethodException e)
            {
                try
                {
                    this.setterMethod = PropertyDefinition.this.modelClass.getDeclaredMethod(this.setterMethodName, this.reflectField.getType());
                }
                catch (NoSuchMethodException e2)
                {
                    // nothing overloaded
                }
            }
        }

        // Here there is a need to type this
        public Object get(Object obj)
        {
            try
            {
                if (getterMethod != null)
                {
                    return getterMethod.invoke(obj);
                }

                return reflectField.get(obj);
            }
            catch (Throwable e)
            {
                throw new RuntimeException(e);
            }
        }

        public void set(Object obj, Object value)
        {
            try
            {
                if (setterMethod != null)
                {
                    setterMethod.invoke(obj, value);
                    return;
                }

                reflectField.set(obj, value);
            }
            catch (Throwable e)
            {
                throw new RuntimeException(e);
            }
        }
    }

    public static PropertyDefinition property(Enum e)
    {
        PropertyDefinition def = propertyDefinitions.get(e);
        if (def == null)
        {
            def = new PropertyDefinition(e);
            propertyDefinitions.put(e, def);
        }

        return def;
    }
}

[1] [http://freddy33.blogspot.com/2007/05/why-java-enum-cannot-extends.html]

Donnerstag, 17. Dezember 2009

Printer is not accepting job

As a Java programmer you might have experienced this message already. And I bet, you were not happy with it.

You'll see it, e.g. if the printer has been turned off and the windows spooler treats the printer as offline.
Which is not that bad, as the spooler itself is still capable to receive print jobs and queue them until the printer is online again.

But not so Java. Java simply ignores the fact that the queue is still accepting jobs - even with JRE 1.6.0_17.

Probably someone mixed up the terms Printer and Queue. If - and only if - the queue is not accepting jobs, Java is allowed to throw an exception.
I am not sure if Windows allows to disable the Queue, the *nix spooler CUPS definitely does.
But actually, Java denies printing even if the Queue is online.

Long story short: If you can afford not having the PrinterIsAcceptingJobs status available in your program - what should be no problem, the following solution is for you.
The solution acutally is just for the Win32 printer service, but should be easily extendable for the *nix one - if you have problems there too.

You need:
  • A Java compiler
  • javassist
And this helper class:

import javassist.CannotCompileException;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;
import javassist.NotFoundException;
import sun.print.Win32PrintService;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.jar.JarEntry;
import java.util.jar.JarOutputStream;

public class Win32PrintServiceFixer
{
 public static void main(String[] args) throws Exception
 {
  ClassPool pool = ClassPool.getDefault();
  instrument(Win32PrintService.class.getName(), pool);

  JarOutputStream jar = new JarOutputStream(new FileOutputStream("target/PrintServiceFixer.jar"));
  addClass(jar, Win32PrintService.class.getName(), "java");
  jar.close();
 }

 private static void addClass(JarOutputStream jar, String clazz, String target) throws IOException
 {
  byte[] buf = new byte[8192];
  int read;

  String name = clazz.replace('.', '/');

  JarEntry jarEntry = new JarEntry(name + ".class");
  jar.putNextEntry(jarEntry);

  InputStream is = new FileInputStream("target/" + target + "/" + name + ".class");
  do
  {
   read = is.read(buf);
   if (read > 0)
   {
    jar.write(buf, 0, read);
   }
  }
  while (read > -1);
  is.close();
 }

 private static void instrument(String clazz, ClassPool pool) throws NotFoundException, CannotCompileException, IOException
 {
  CtClass ctClass = pool.get(clazz);
  for (CtMethod cMethod : ctClass.getDeclaredMethods())
  {
   if (cMethod.getName().equals("getPrinterIsAcceptingJobs"))
   {
    System.err.println("replacing getPrinterIsAcceptingJobs");
    cMethod.setBody("return javax.print.attribute.standard.PrinterIsAcceptingJobs.ACCEPTING_JOBS;");
   }
  }
  ctClass.writeFile("target/java");
 }
}

This helper looks up the Win32PrintService class and instrument the bytecode in a what that the check for "PrinterIsAcceptingJobs" always returns: Yes, the printer is accepting jobs.
Finally, it bundles the resulting class in a jar file named PrintServiceFixer.jar - created in a directory named "target".

You should see

replacing getPrinterIsAcceptingJobs
on the console output. If this line is missing, your JDK/JRE version needs another trick.

Now you have to start your program with the "bootclasspath" option like this:

-Xbootclasspath/p:target/PrintServiceFixer.jar

Java will load our patched version of Win32PrintService instead of the original one - and - tata - your program no longer suffers from

javax.print.PrintException: Printer is not accepting job
exceptions.

Best will be you create a jar file per JRE/JDK version you use and carefully use the right version, else you might encounter more problems than you are going to fix.

If you would like to fix the PrintService for your platform, try to find the Class name of the platform dependent PrintService implementation and see if there is a method like "getPrinterIsAcceptingJobs". Change the helper class above accordingly and run it.

Another option to fix that problem is to use AspectJ with runtime weaving, but I often found myself to be too impatient with the resulting slower startup times of the application.
Anyway, you know what you should looking for now and it should be easy enough to create a pointcut.

Happy printing!

Donnerstag, 5. März 2009

Avaje - Repeatable Read and Auto-Fetch

code hosted at copy-con-goodies

Today I'll tell you something about Avaje, my new best friend for database access.

First of all, one can not say that this library is bug-free, but Rob (as far as I know the main developer) makes a very good job in applying my patches ;-).
Seriously, it is an awesome piece of code which is just to young to work in each and every use-case JPA is designed for. What makes it my fav is, that I managed to dig into the code in just one weekend. Nicely structured!

Repeatable Reads

The first thing you have to take into account - compared to any other JPA implementation - is, that Avaje does not need a PersistenceContext, for an Web-Application this means, you do not have to make sure you issue each database request against the same PersistenceContext.
If you look at this example you can find the following lines of code:
    // read entity without transaction ... this automatically creates one just for this very statement
    TestEntity readEntity1 =
        server.find(TestEntity.class, 1L);

    // and again. We now read the same database row but got two independent instances
    TestEntity readEntity2 =
        server.find(TestEntity.class, 1L);
Withouth any provisioning you will get two instances of the same row. Sure, you have to keep in mind that, if you change and update readEntity1 and later on you do the same with readEntity2 you will face a concurrent modification and get an exception. But how often will you have to deal with that on a web-page?

Now, if you need the feature to get the same instance for the same entity you simply put a transaction around, so the code above becomes:
    // now lets start a transaction
    Transaction tx = server.beginTransaction();
    TestEntity readEntity1_1 =
        server.find(TestEntity.class, 1L);

    TestEntity readEntity2_1 =
        server.find(TestEntity.class, 1L);

    // we now got the same instance for the same row  
    tx.commit();
This effectively means you can have the best of both worlds. Normally you would not care about "repeatable reads" and simply use your entities, if (for example you start multiple processes to update various data) you need to ensure to get the same instance from an database access you simply put a transaction around.
And this is something you would do anyway as you will update data, no?

Auto-Fetch

Another VERY nice concept of Avaje is auto-fetch.
I've added a little code to the exaple code above which allows you to dig into that feature.
I will see I access the property field1 and field2 from the various bean instances.
  readEntity1.getField1(); // read content of field1

  readEntity2.getField2(); // read content of field2
On the first run the sql for reading readEntity1 you will see Avaje will fetch (not very surprisingly) all the properties from the database
<sql summary='[TestEntity]'>
    select e.ID c0, e.FIELD_1 c1, e.FIELD_2 c2, e.VERSION c3 
    from TEST_ENTITY e
    where e.ID = ?  
</sql>
But at the end Avaje will collect the statistics and persist them into a local file using the .autofetch extensions.
Now, on the second run the sql will look different
<sql summary='[TestEntity] autoFetchTuned[true]'>
    select e.ID c0, e.FIELD_1 c1, e.VERSION c2 
    from TEST_ENTITY e
    where e.ID = ?  
</sql>
Do you notice? FIELD_2 is no longer fetched from the database.
It might happen that you change your code, or your programm takes other routes through the code and it requires FIELD_2 now, Avaje will fetch the field lazily and learn this fact. Next time it will prefetch it too.

This also works for e.g. OneToMany associations. This means, you no longer have to think about making an association lazy or not, it also frees you from making associations lazy - and then adding code to load them eager sometimes.
Avaje simply will learn that from your code by capturing the stack-trace and storing access information to these points.

Imagine what a performance boost this can be for your program!

You can find more infomation about this astounding feature here.

Dienstag, 3. März 2009

Apache MyFaces Orchestra

Lately jsfcentral released a podcast which Kito recorded with Simon Kitching and me at JSFDays 2008.

This podcast is about Apache MyFaces Orchestra at its youngest days.

In the meantime a lot of things happend. One thing is, that I started to write a real Rich-Client application using Swing.
I had to reconsider everything ... My well known (so called) web-application-stack was no longer usable. No JSF, no Tomcat, no Servlets.
During this process I also thought about the database access layer. JPA is a great thing (I think), but some stuff around it is ... a hell.

As JPA implementation I use Hibernate which is also a great thing, but in the end, JPA does not necessarily make things easier.
The problem I have with ORM/JPA is the full transparency. It is funny, exactly this concept should makes things easier. But for me, it made things more complicated. It even forced me to build Apache MyFaces Orchestra to have a decent conversation scope.
Sure, I could have used JBoss Seam or Spring Web-Flow. But Web-Flow is to far away from standard JSF (for my opinion) and JBoss Seam ... I simply did not get how it worked.
However, with Orchestra there is simply a third choice, and all three choices are working very well ... if ... yes, if you would like work transparently with your entities (database objects).

  1. Transparently means, you change a property and somewhere at the end of the conversation a commit() finally persist it.
  2. Another thing which ORM solves are repeated reads of an entity with the same primary key. The ORM implementation will simply fetch it from the in-memory cache and you will always see the same instance.
    This is fine as if you changed the entity somewhere else you can be sure to see this change without having it persisted to the database.

Other stuff like lazy loading of associations or the database-independent creation of SQL statements can be expected from any other database access layer too, not neccessarily being 100% transparent, though.

Ok, (1) and (2) are really nice to have, but is it that a deficit not to have that?
I never managed to have that a perfect object hierarchy so that I did not have to call at least PersistenceContext.save(entity). Creating such a perfect object hierarchy is not easy and I doubt that it will lead to an overall performant database access.
And for (2): When are those repeated reads really necessary to being handled at "database session" level?
Even with Orchestra you can simply cache the entity yourself in the conversation-scoped backing bean of your JSF page. The only requirement which pops into my mind are "processes". Think about processes as various business modules of your appliation you compose together to a business-process.
But this composition will run normally within the same "transaction", so it is sufficient to have this "repeatable read" stuff working just for the "time of a transaction".
Hmmm ... I should write about that separately.

Once you buy that, you will find yourself writing easier maintainable programs. You just have full control over what happens when and why again.

To sum up:
  • Do not mind to call something like .save(), .delete()
  • Cache your entity as long as required and do not rely on "repeatable read"

The good thing is, that Orchestra is still usable in this scenario as the conversation scope is usable anyway - it defnitely will make your web-application development easier - but it is no longer required to have the persistence context being synchronized with the lifetime of the conversation. You simply use Orchestra without any PersistenceContextInterceptor.

The downside here is the requirements of JPA which will not play nicely here due to the "session" data it maintains to make all the transparency work.

Thanks to Simon Kitching who pointed me to Avaje I became aware of a library which works much like a JPA database access layer, but keeps a database session just for the transaction time. EXACTLY what I searched for.
Being able to stick with well known annotations, but without all the hassle you have with the 100% transparency "forced" by JPA.

My code did not change that much. But no session cache bloats my memory, no unused entities are hanging around in memory which you have to get rid somehow, no nested conversations if you e.g. navigate to a search page and back again.
It is hard to express, and a Blog is all about writing about personal feelings, but if you too think that JPA - as it is now - can't be the end, have a look at Avaje.
My next blog will be about Avaje ... stay tuned.

Montag, 2. März 2009

What is "copy con"?

Well, I am getting old, and so I undergo a lot of hassle with computers.

One of those was when something (no, it was not me ;-) ) crashed your ms-dos config.sys file (for those who remember) which you had no backup of ... as usual.

Once, due to the absence of any working editor, I had to use "copy con" to recreate this file.

So
copy con: config.sys
allowed me to copy the CONsole input to a new config.sys.

Care had to be taken taken to enter everthing correct the first time, else you had to start over as there was no way to edit previously entered lines.

Thas was fun!

BTW: This still works even with Windows 2008, for sure, no config.sys, but try
copy con: blog.txt
- and enter some text. (To stop editing you have to press "Ctrl-Z" and Enter)