Česky   |  Deutsch   |  English   |  Español   |  Français   |  Indonesia   |  日本語   |  한글   |  Polski   |  Português (BR)   |  Türkçe   |  中文   |  正體中文   |  Your Language  
PlanetNetbeans
Planet NetBeans is an aggregation of NetBeans related musings from all over the Blogosphere.
Feeds
[RSS 1.0 Feed] [RSS 2.0 Feed]
[FOAF Subscriptions] [OPML Subscriptions]
Do you blog about NetBeans ? Add your blog to PlanetNetBeans.
Feed Subscriptions
APIDesign - Blogs (feed)
David R. Heffelfinger (feed)
Carsten Zerbst's Weblog (feed)
Winston Prakash's Weblog (feed)
NetBeans – Michael's blog (feed)
DukeScript (feed)
ProNetBeans (feed)
Paulo Canedo » NetBeans English (feed)
Anchialas' Java Blog (feed)
markiewb's blog (feed)
Need to find a title (feed)
Category: NetBeans | Software and Science (feed)
Roger Searjeant's blog (feed)
Inspiration and Expression » Netbeans (feed)
Adam Bien (feed)
Michel Graciano's Weblog (feed)
Ramon.Ramos (feed)
Ozone and Programming » netbeans (feed)
NetBeans Ruminations » NetBeans (feed)
NetBeans – Java PDF Blog (feed)
Arun Gupta, Miles to go ... (feed)
Geertjan's Blog (feed)
.JARa's Bilingual Weblog (feed)
JavaFX Composer (feed)
The Java Jungle (feed)
Jesse Glick (feed)
Martin Grebac (feed)
The NetBeans Community Podcast (feed)
NetBeans Profiler (feed)
NetBeans for PHP (feed)
NetBeans Web Client (feed)
Rechtacek's (feed)
Virtual Steve (feed)
The Aquarium (feed)
Tinuola Awopetu (feed)
Insert Witty Irony Here (feed)
Netbeans – Gualtiero Testa (feed)
netbeans – James Selvakumar’s Blog (feed)
NetBeans – nB gUru (feed)
netbeans – Newsintegrator Blog (feed)
NetBeans – Praxis LIVE (feed)
NetBeans – TechAshram (feed)
Netbeans – There's no place like 127.0.0.1 (feed)
Anuradha (feed)
Netbeans6/6.5 my best practices (feed)
Java Evangelist John Yeary (feed)
Neil's Dev Stuff (feed)
Computer says null; (feed)
NetBeans Adventures, Java and more (feed)
NetBeans – John O'Conner (feed)
Bernhard's Weblog (feed)
NetBeans Community Docs Blog (feed)
The Netbeans Experience (feed)
NbPython/ jpydbg / pymvs (feed)
Shanbag's Blog (ರಜತ ಲೋಕ) (feed)
Wade Chandler's Programming Blog (feed)
Devlin's Lab (feed)
Big Al's Blog (feed)
Code Snakes (feed)
In perfect (spherical) shape (feed)
Van Couvering Is Not a Verb (feed)
Diego Torres Milano's blog (feed)
Vroom Framework (feed)
Messages from mrhaki (feed)
Jeff's Blog (feed)
Manikantan's Netbeans (feed)
Oliver Wahlen's Blog (feed)
Shuttle between Galaxies (feed)
Welcome to my live... (feed)
Devel Blog (feed)
diamond-powder (feed)
Antonio's blog (feed)
Where's my Blog?!

Powered by:    Planet

Last updated:
August 28, 2016 10:05 PM
All times are UTC

Sponsored by
sponsored by Oracle

visit NetBeans website
markiewb's blog - August 28, 2016 11:52 AM
Quicktips: Nice little features in NetBeans’ JS-Editor

Currently there is a MOOC on Oracle JET (https://blogs.oracle.com/geertjan/entry/sign_up_free_today_oracle), which I am attending. I am not a JS developer for my daily living, so there was no need for me to use the JS editor of NetBeans until now. So I was surprised by some cool features in NetBeans 8.1:

  • Drag & Drop of js files into HTML generates script tags
    2016-08-28 13h49_57.gif
  • Pressing ‘ or ” or ( or { on a selected text encloses the text
    2016-08-28 13h56_18.gif
    2016-08-28_14h14_04.png

Geertjan's Blog - August 27, 2016 07:00 AM
Avoiding Hiccups in Building Oracle JET Applications

When using NetBeans IDE to work on an Oracle JET project installed using the Yeoman generator on the command line, the files in the "src" folder are incomplete without the build command being run. Of course, you can just enable the Grunt build task and that solves that issue. Just right-click on the project and choose Build:

The first time you do this, you'll be prompted as follows:

Say Yes and you'll be here (your version of the below may be different to mine since I'm using a development build of NetBeans IDE):

Note that I checked the "Build Project" checkbox, which has "build" in there by default. When I click OK out of the dialog above, and then try to build the project again, I see the following in the Output window:

"C:\nodejs\grunt.cmd" "build"
Running "build" task

Running "oraclejet-build:undefined" (oraclejet-build) task
 Oracle JET Grunt plugin 
Processing Grunt command...
 [Warning] Missing platform. Default to web. 
Theme Name:Platform - alta:web 
Theme Version - 2.1.0
cleaning staging path.....
copy files to staging directory.....
copy finished...
compiling sass....
sass compile skipped...
running theme injection task.....
indexHtml theme path injection finished..
running theme copy task.....
theme copy finished...
running injection task.....
mainJs paths injection finished..

Done.
Done.

At this point, you need to be very careful. The process above has created a "web" folder, as shown below:

Note: The "web" folder is where things need to be "run" from to see the real app, while the source files should only be edited in the "src" folder. Be careful that you do not run into the issue of editing the "web" files and then losing your work when you do the next build. Be aware that the "web" folder is completely overwritten when you do a build.

Only after you have done the build, can you do "grunt serve", which will serve up the application into the platform of choice, which is the browser by default.

Geertjan's Blog - August 26, 2016 05:48 PM
Application Templates in Oracle JET

Here's an overview of each of the Oracle JET application templates in Oracle JET 2.1.0.

Note: Below each of the Yeoman generator commands below, you see how the project looks in NetBeans IDE. I.e., just go to File | Open Project, browse to the folder where you ran the commands below and you'll simply be able to open the project into NetBeans IDE.

yo oraclejet app1 --template=blank

yo oraclejet app2 --template=basic


yo oraclejet app3 --template=navbar

yo oraclejet app4 --template=navdrawer

The "blank" template above is completely blank. It has Oracle JET wired up and a blank "index.html" content body. The starter templates, "basic", "navbar", and "navdrawer" are described in detail on the Oracle JET site here.

Tip: If you're following the Oracle JET MOOC and using the Yeoman generator, you're advised to use "navbar" or "navdrawer", since these provide a set of Oracle JET modules, as can be seen above, which you can immediately start using to learn and develop your Oracle JET applications.

In addition to the above, there are project templates in NetBeans IDE, if the Oracle JET Support plugin is installed. These provide different results to the above.  Via the Oracle JET Support plugin, you have the "Oracle JET Base Distribution" template which is even more blank than the 'blank' template above. It contains the Oracle JET distribution, without any template files at all, and with Oracle JET being wired up less than the 'blank' template above.

Note: You also have the "Oracle JET QuickStart Basic" template, provided by the Oracle JET Support plugin in NetBeans IDE, which creates the application template that is used throughout the Oracle JET MOOC, i.e., with a "home" Oracle JET module, among other Oracle JET modules. As you can see above, the Yeoman generator does not produce a "home" module, though that doesn't matter at all, you can use any of the other Oracle JET modules that your template provides, no need to worry therefore if you're missing a "home" module when you're following instructions in a tutorial or the Oracle JET MOOC.

Alternatively, you can download ZIP files here, including the "Oracle JET QuickStart Basic", here:

http://www.oracle.com/technetwork/developer-tools/jet/downloads/index.html

APIDesign - Blogs - August 26, 2016 10:37 AM
Swing's Bad Reputation

Is Swing's openness reason for its so bad reputation?

--JaroslavTulach 10:37, 26 August 2016 (UTC)

NetBeans – Michael's blog - August 25, 2016 09:21 PM
NetBeans rocks JShell

Some weeks ago I posted about “Cool stuff: NetBeans and JShell” [1]. Sadly, JShell did not observe the editor if the editor (e.g. gedit) had not been started from within the shell. Thus, you could not have used NetBeans as editor if the shell had been started within the NetBeans terminal window. I discussed this … Continue reading "NetBeans rocks JShell"

Geertjan's Blog - August 25, 2016 10:10 AM
Adding Some Color to the RebelLabs Developer Productivity Report 2016

I used to have a very nice colleague who would never disagree with me. He'd never say 'I disagree with you'. Instead, he'd always say, 'let me add some color to that', after which he'd proceed to, essentially, disagree with me. :-) [I miss you, Ashwin!] But it was a nice experience. He wasn't disagreeing, he was adding color.

In that light I'd like to look at an aspect of the RebelLabs Developer Productivity Report 2016. It wasn't released very long ago and has the following results for IDE usage:

On the face of it, things aren't looking so great for NetBeans! In fact, NetBeans is doing very badly indeed. You can't really talk about "the top three IDEs" anymore, there's clearly only "the top two IDEs". However, let's look a bit more closely and ask ourselves some questions. Yes, let's add some color to that!

ZeroTurnaround & Me

Let me start by saying I love the ZT team. I have known several members of ZT for a lot of many years.

Jevgeni I remember meeting at JavaZone in Norway many years ago when he was talking about his Aranea web framework; Anton I have done several JavaOne sessions with; the JRebel plugin for NetBeans is one of the most actively developed NetBeans plugins; Igor has created the most amazing MindMap plugin for NetBeans; I've talked to Simon at several conferences; Alan and Michael I met in Denmark and I claim some role in surfacing them in the community and getting them noticed by Jevgeni (watch this cool YouTube clip with Alan, Fabrizio, and me); Oleg I spent a crazy time with in the Bering Sea; Sang, Adam, and Geert who used to work there are guys I have known forever as well. And, on top of all that, ZeroTurnaround is a NetBeans partner.

So, again, I am really adding color here and seriously not trying to do anything other than that. I love ZT, OK.

Tone & Content

In the report: "Overall we received 2044 responses." Moreover, when I see the response to "What is your job description?", I don't see anything about "I am a student". In fact, the word "student" doesn't appear in the report. Nothing at all wrong with that, of course. The survey was not aimed at students at all.

Already one can feel the kind of color that can be added here. Slightly over 2000 respondents, which seems small to me. And no students.

Plus, it took quite a bit of motivating to get those 2000 respondents. Especially the last few hundred took some work, I saw quite a bit of activity in getting those, e.g:

You know who else didn't participate? The NetBeans community. On 1 March this year, there was a brief discussion on the NetBeans Dream Team mailing list. The NetBeans Dream Team is a group of volunteers outside of the NetBeans team and outside of Oracle. They're NetBeans enthusiasts who are recognized for their activism by being invited to join the group to share insights and activities and ideas around NetBeans. We discussed the RebelLabs productivity reports. Especially the fact that the tone of the reports is definitive and assertive, despite not covering at least the simplest of these concerns, i.e., a pretty low number of self-selecting respondents, none of whom are students which is a key demographic that NetBeans has targeted from the beginning.

My suggestion was that this year, in contrast to previous years where we were a bit sceptical too, we go full on for the survey, promote it to the community, to the NetBeans enthusiasts around the world, the mailing lists, etc. However, one of the people in the discussion suggested, bearing in mind our objections: "Instead of helping them with extra data points you might just publicly ask NetBeans users to NOT respond to RebelLabs surveys." I disagreed strongly because I love ZT! And ZT is a NetBeans partner, on top of that.

So, we did nothing. We let it go, knowing that by not promoting this to the NetBeans community, the results would probably be like they turned out to be. The results of the survey provide a limited view on a self-selecting segment of the Java community.

Reap & Sow

However, let's go a bit further. Given the limitations outlined above, which in themselves disqualify the results, or should disqualify the results from being used to say anything about the actual usage of the tools, is there an explanation for those 2044 respondents having responded in the way they did? Why did only 10% of those problematic non-student 2044 respondents pick NetBeans?

JetBrains is incredibly admirable for their conviction. JetBrains supports their tools without a second of doubt. Oracle, well, not so much. Sometimes yes, sometimes no. Sometimes lots of enthusiasm, sometimes just a bit, something nothing. The last time NetBeans had an evangelism team was in the days of Roman Strobl, I guess around 2007 or so, when NetBeans was part of Sun and when there were about 10 fulltime NetBeans evangelism staff (in addition to about 6 technical writers, of which I was one) constantly and consistently promoting NetBeans. There's nothing left of that. Well, just me, plus the NetBeans Dream Team, an unpaid volunteer force to be reckoned with, but not a paid staff strategizing and planning the best way to reach developers with tools etc. Meanwhile, JetBrains has been investing in that aspect of its organization to great effect. Kudos to them.

To add some color to the results, therefore, I tentatively suggest that they are a reflection of the conviction versus the ambivalence of the organizations behind those tools, as well as the staffing and strategies for promoting them. On this basis, the percentages mirror the backing that the tools have received from the organizations that sponsor them.

Apples & Pears

We need to go further still and ask the "why" question. What's the reason for the different levels of enthusiasm of these organizations for their tools? JetBrains and Oracle have completely different aims, of course. JetBrains is explicitly a tooling company. The key slogan, a really good one, is: "Whichever technologies you use, there's a JetBrains tool to match."

Oracle, on the other hand, is historically a database company and increasingly a Cloud company. In contrast to JetBrains, for Oracle tooling plays, at best, a supporting role, and is, at worst, an after thought. Though one would expect tooling to play a bigger role, it tends to fall a bit by the wayside in the final push to a technology release.

Facebook & Twitter

So, if the ZT survey cannot accurately reflect IDE usage, is there another way to conclusively do so. No. The only thing anyone can provide are very tentative indicators.

Here are some:

What does the above show? One thing I find interesting is that JetBrains is spending a lot of energy while not getting as compelling a result as the other two IDEs. Also note that normally Eclipse doesn't have as much engagement on Facebook as this week. The last few weeks have been special because of Eclipse Che, generating a lot of engagement. NetBeans, though, is clearly on top in terms of Facebook likes. Note also that there's never more than one or two new items on the NetBeans Facebook page per day. Sometimes nothing. Because we don't want the news from yesterday to get lost. So we add one new item every other day or so. A different strategy to JetBrains, clearly, which also has to contend with the fact that IntelliJ IDEA is only one of their tools. They have a lot to talk about, though it doesn't seem to result in a lot of new Facebook likes.

Next, let's take a look at Twitter followers. Below you see NetBeans, then JetBrains, then Eclipse. Again, NetBeans has the most followers, i.e., the most people interested in receiving tweets from one of the three IDEs is from people interested in NetBeans. Again, notice the disparity between the amount of tweets from JetBrains versus the considerably lower number of followers:

Of course, someone will say, this says nothing about what people are working with. Hmmm. I wonder about that. How many Twitter accounts do you follow of tools that you're not using? And if you want to see a comparison between real tool usage, take a look at the difference between the number of people using the Chrome plugin for NetBeans versus the Chrome plugin for IntelliJ:

That's a difference of about 50,000, which has been constant, plus or minus a few thousand, over the past years.

If you were to want to reach as many developers as possible, with your message, or your technology via a plugin, which of the three IDEs would you immediately suspect could be used to reach the largest number of people? Over on YouTube, look at the marked difference in views between two different YouTube clips, about the same technology, i.e., Oracle Developer Cloud Service, installed in Eclipse vs. installed in NetBeans:

The two YouTube clips were created in the same period. The Eclipse YouTube clip has less than 300 views, while the NetBeans equivalent has around 4000 views. Neither of those numbers are very high, which is probably because Oracle Developer Cloud Service is an extremely non-sexy topic. Nevertheless, the NetBeans views are orders of magnitude higher, clearly.

Of course, I am not arguing that NetBeans is the most popular IDE. I don't believe that to be true at all, in fact. Plus, that's not the point I am making here, in any way. No one can make that claim. I am simply adding color to the survey results, since these different statistics from completely different sources appear to indicate something different to what the survey suggests.

Intention & Abuse

Where it becomes dangerous is where the ZT survey is used as a stick to beat an IDE with. That was never the intention of the awesome people at ZT, though it is exactly what happens when surveys are released.

Surveys are always flawed and never present the full picture. Like when I argued with (ah, 'added color to') the RedMonk survey a few years ago, if we don't have the full climate picture, we shouldn't be doing the weather report. At the very least we should be extremely circumspect and not assert anything at all lest our assertions be abused in contexts for which they were never intended.

Adam Bien - August 25, 2016 07:12 AM
HAProxy, TomEE 7.01 Plus, Elasticsearch -- New Docklands Images Arrived

HAProxy, TomEE 7.0.1 Plus and Elasticsearch Docker images were added to github.com/AdamBien/docklands. Docklands already comes with minimalistic images for Postgress, DerbyDB,Tomcat, Payara Server (aka commercially supported GlassFish), WildFly, Weblogic and WebSphere Liberty Profile.

Docklands layering (image inheritance) aims for build speed, low memory overhead and productivity.

I'm using docklands as base for my consulting work and many microservices projects.

See you at Java EE Workshops at Munich Airport, Terminal 2 and particularly at Java EE 7 Microservices. Is MUC too far? Checkout http://javaeemicro.services


Real World Java EE Workshops [Airport Munich]>

Geertjan's Blog - August 24, 2016 03:14 PM
Oracle JET MOOC - Tips & Tricks (Part 1)

We're really pleased with the level of activity around the Oracle JET MOOC. Monday next week, when the 2nd week starts, we'll close registration, at which point we expect to have around 2,000 participants. The MOOC will run again, for free, in October, after OpenWorld and JavaOne.

We've picked up on some common problems on the Oracle JET forum and have put together some tips and tricks, as well as news and updates, here:

<span id="XinhaEditingPostion"></span>

We expect to release a similar YouTube clip part way through the 2nd and 3rd week of the course.

Geertjan's Blog - August 20, 2016 10:33 AM
Integrating Oracle Fusion Middleware MapViewer with Oracle JET

There are many map components in the world out there—and I have documented how to integrate several of them in an Oracle JET application, e.g., 3DCityDB, Mapbox, Leaflet, and LuciadRIA, as well as Oracle JET's ojThematicMap component

However, Oracle has its own map component, as described in detail below, which includes the Oracle Maps Javascript library:

http://www.oracle.com/technetwork/middleware/mapviewer/overview/index.html

Oracle Fusion Middleware MapViewer is a development toolkit for incorporating interactive maps and spatial analyses. It is optimized for use with Oracle Spatial and Graph. (The related Oracle blog is blogs.oracle.com/oracle_maps_blog.) Here below is how it looks when integrated into an Oracle JET application, with many thanks to my colleague Jayant Sharma, who made it happen and provided the instructions that follow, which I have successfully used and I can report that it works.

Instructions for integrating Oracle Fusion Middleware MapViewer with Oracle JET, assuming you have set up an Oracle JET application, e.g., via the Oracle JET QuickStart Basic template:

  1. Add the Oracle Maps V2 kit into js/libs as a folder named 'oraclemaps'. The kit can be downloaded from here and specifically here: http://download.oracle.com/otn/other/mapviewer/12c/12211/v2_122110_full.zip

  2. Modify "main.js" to include the various Oracle map libraries, in the requires.config "path" and "shim" sections. I.e., add these entries in the "paths" section:
    //File paths for Oracle Maps HTML5 API
    'omapsv2-hammer': 'libs/oraclemaps/v2/jquery/jquery.hammer-full.min',
    'omapsv2-i18n-properties': 'libs/oraclemaps/v2/jquery/jquery.i18n.properties-min-1.0.9',
    'omapsv2-mousewheel.min': 'libs/oraclemaps/v2/jquery/jquery.mousewheel.min',
    'omapsv2-rtree': 'libs/oraclemaps/v2/rtree/rtree-min',
    'omapsv2-fortknox': 'libs/oraclemaps/v2/fortknox-libs/fortknox-canvas',        
    'omapsv2_core': 'libs/oraclemaps/v2/oraclemapsv2_core'

    ...and these in the "shim" section:

    //Oracle Maps HTML5 API dependencies
    'omapsv2-i18n-properties':  ['jquery'],
    'omapsv2-hammer': ['jquery'],
    'omapsv2-mousewheel.min' : ['jquery'],     
    'omapsv2_core': {
       deps: ['jquery','hammerjs','omapsv2-fortknox','omapsv2-rtree','omapsv2-hammer','omapsv2-i18n-properties','omapsv2-mousewheel.min'],
       exports: 'OM'
    }
  3. Modify the view of an Oracle JET module, e.g., "home.html", in the way it's done for the MapBox example, i.e., rewrite "home.html" to be the following and include "css/styles.css" containing "#map { width:100%; height:100%; }": 
  4. <STYLE TYPE="text/css">
    <!--
      @import url(css/styles.css);
    -->
    </STYLE>
    
    <div id='map'></div>
    
  5. Modify the viewModel of an Oracle JET module, e.g., "home.js", to be as follows, and read the comments below to understand the code:
    define(['ojs/ojcore', 'knockout', 'omapsv2_core'],
        function (oj, ko) {
            function mainContentViewModel() {
                var self = this;
                self.handleAttached = function () {
                    /* */
                    if (OM !== undefined) {
                        //Where to load Oracle Maps HTML5 API resource files (fonts, css and icons et al):
                        OM.gv.setResourcePath("js/libs/oraclemaps/v2");
                        //Default http method when fetching remote geospatial contents:
                        OM.gv.setHttpMethod("GET");
                    } else
                        console.log('OM not loaded');
                    var X = -77;
                    var Y = 38.9;
                    var initialZoom = 11;
                    //This function adds various map controls to the provided OM.Map instance:
                    var addMapControls = function (myMap)
                    {
                        //defines various properties for the navigation control:
                        var navConfig = {
                            orientation: 1,
                            style: OM.control.NavigationPanelBar.STYLE_ZOOM_BUTTONS_ONLY,
                            anchorPosition: 1
                        };
                        //creates the navigation control:
                        var navigationControl = new OM.control.NavigationPanelBar(navConfig);
                        // navigation control (and other map controls) are typically added
                        //to the map as map decorations:
                        myMap.addMapDecoration(navigationControl);
                        //defines the basic properties for the map scale bars:
                        var sbConfig = {
                            format: "BOTH",
                            anchorPosition: 4,
                            endMarks: false
                        };
                        //defines the display style of the scale bars:
                        var sbStyle = {
                            thickness: 5,
                            color: '#257db3',
                            shadow: true
                        };
                        //creates the actual scale bar instance and sets the display style:
                        var scaleBar = new OM.control.ScaleBar(sbConfig);
                        scaleBar.setStyle(sbStyle);
                        //adds the scale bar to the map as another map decoration:
                        //myMap.addMapDecoration(scaleBar);   
                    };
                    var showMap = function ()
                    {
                        //This is the DIV that will display the map; it needs to be passed into
                        //the map instance:
                        var mapDiv = document.getElementById('map');
                        if (!mapDiv)
                        {
                            console.log("Map container DIV not found!");
                            return;
                        }
                        //Creates a new map instance. Notice we are not supplying a Universe
                        //like in helloworld.js, since the universe will be defined when we
                        //add the tile layer to the map. Every tile layer includes its own
                        //universe definition as part of the tile layer's configuration:
                        var map = new OM.Map(mapDiv, {mapviewerURL: ''});
                        //This is how we create an Oracle eLocation tile layer: by creating
                        //a new instance of the OM.layer.ElocationTileLayer class. Check
                        //the <a href="https://apidoc/index.html">API Doc</a> for other built-in tile 
                        //layers such as Bing maps:
                        var tileLayer = new OM.layer.ElocationTileLayer("elocation");
                        //Adds the tile layer to the map:
                        map.addLayer(tileLayer);
                        //creates a point object located at the given longitude and latitude: 
                        var point = new OM.geometry.Point(X, Y);
                        //Adds various map controls to the map:
                        //console.log('adding mapControls');
                        addMapControls(map);
                        // set the initial map zoom level and center (same as the location marker):
                        map.setMapCenter(point);
                        map.setMapZoomLevel(initialZoom);
                        //Now we can complete the initialization of the map. You must
                        //only call this method once.  Note however map layers can
                        //be added even after calling this method:
                        map.init();
                    }; //showMap
                    // console.log('call showMap');
                    showMap();
                    /*  */
                }; // handleAttached
            }
            return new mainContentViewModel();
        });

That's it. Run the project and you'll see the same as in the screenshot above.

Geertjan's Blog - August 19, 2016 04:15 PM
Translating Oracle JET Applications

The Oracle JET MOOC starts on Monday. When we talk about Oracle JET we always say that it solves "enterprise challenges". One of these is internationalization/localization/translation of JavaScript applications. Recently I started playing with the translation features of Oracle JET and they're pretty impressive. Really, if you want to create JavaScript applications that need to be translated, you should look no further than Oracle JET.

Let's start by looking at the result of a small sample I've been working on. Here's an application that can be switched to 4 different languages, with a screenshot of 3 of them below: 

Everything to achieve the above is documented in "Internationalizing and Localizing Applications" in the Oracle JET Developer Guide. This topic is also dealt with in the 3rd week of the Oracle JET MOOC.

There are several bits and pieces involved in this sample: 

  1. Bundled translations for Oracle JET components. Oracle JET components, such as the date/time picker that you see above, have already been translated. The translations are found in libs/oraclejet/dist/js/libs/oj/resources/nls.

  2. Custom translation bundles. Aside from the Oracle JET components, which have already been translated, Oracle JET provides a facility for storing and loading your own translations. Below, you can see a folder called "resources/nls", with subfolders for each of the languages I am supporting:



    In "main.js", I have this, which registers the "resources/nls/l10" structure and merges it with the translations that are provided by Oracle JET:
    config: {
        ojL10n: {
            merge: {
                'ojtranslations/nls/ojtranslations': 'resources/nls/l10'
            }
        }
    }

    The most important file in "resources/nls" is the file named "l10.js", which could be named anything at all, so long as it matches the registration in "main.js" shown above. It looks like this, in my case:

    define({
      "root": {
        "date": "Date:",
        "greeting": "Good Morning"
    },
      "ar": true,
      "fr": true,
      "cs": true
    });
    In each of the folders that have been enabled above, i.e., "ar", "fr", and "cs", translations of the above texts are found, e.g., in "ar":



    Now, anywhere in our viewModel, we can use this statement to retrieve the greeting of the current locale:
    oj.Translations.getTranslatedString('greeting')
  3. RTL Support. Bidirectional features are included too, read here, simply by setting the "dir" attribute of the "html" element to "rtl" and back to "ltr".

  4. Dynamic Locale Switching. Via the buttons you see above, the locale can be switched, as described here.

Following from the above, the complete code for the viewModel is as follows, focused on enabling the switching between locales, which will cause the translation bundles to be loaded dynamically:

define(['ojs/ojcore', 'knockout', 'ojs/ojbutton', 'ojs/ojdatetimepicker'],
    function (oj, ko) {
        function mainContentViewModel() {
            var self = this;
            self.formats = ko.observableArray(["english"]);
            self.date = ko.observable();
            self.greeting = ko.observable("Good Morning");
            self.localeDate = ko.observable();
            self.localeDate(oj.Translations.getTranslatedString('date')); 
            self.localeGreeting = ko.observable();
            self.localeGreeting(oj.Translations.getTranslatedString('greeting')); 
            self.setLang = function (data) {
                var newLang = '';
                switch (data) {
                    case 'Arabic':
                        newLang = 'ar-EG';
                        self.formats(["arabic"]);
                        break;
                    case 'Czech':
                        newLang = 'cs-CZ';
                        self.formats(["czech"]);
                        break;
                    case 'French':
                        newLang = 'fr-FR';
                        self.formats(["french"]);
                        break;
                    default:
                        newLang = 'en-US';
                        self.formats(["english"]);
                }
                oj.Config.setLocale(newLang,
                    function () {
                        $('html').attr('lang', newLang);
                        if (newLang === 'ar-EG') {
                            $('html').attr('dir', 'rtl');
                        } else {
                            $('html').attr('dir', 'ltr');
                        }
                        self.localeDate(oj.Translations.getTranslatedString('date')); 
                        self.localeGreeting(oj.Translations.getTranslatedString('greeting')); 
                        $('#dateInput').ojInputDateTime('refresh');
                    }
                );
            };
        }
        return new mainContentViewModel();
    });

And here's the view:

<div data-bind="ojComponent: {component: 'ojButtonset', checked: formats}">
    <!--Arabic-->
    <label for="arabic">Arabic</label>
    <input data-bind="click: function(){setLang('Arabic');}" 
           type="checkbox" value="arabic" id="arabic"/>
    <!--Czech-->
    <label for="czech">Czech</label>
    <input data-bind="click: function(){setLang('Czech');}" 
           type="checkbox" value="czech" id="czech"/>
    <!--French-->
    <label for="french">French</label>
    <input data-bind="click: function(){setLang('French');}" 
           type="checkbox" value="french" id="french"/>
    <!--English-->
    <label for="english">English</label>
    <input data-bind="click: function(){setLang('English');}" 
           type="checkbox" value="english" id="english"/>
</div>
<br/>
<br/>
<span style="font-size: 50pt" id="greeting" data-bind="text: localeGreeting"></span>
<br/>
<span data-bind="text: localeDate"></span>
<input id="dateInput" type="text" 
    data-bind="ojComponent: {
        component:'ojInputDateTime', 
        value: date,
        datePicker: {changeMonth: 'none', changeYear: 'none'}
    }"/>

That's it. And here's the sample code shown above:

https://github.com/GeertjanWielenga/OJETCourse/tree/master/Part-024

A next step is to generate all the buttons automatically from JavaScript, i.e., there should be some way to provide new buttons to switch to new languages easily, without having to code them in HTML, i.e., in the viewModel, find the lists of available translation locales and create the buttons, and their logic, based on that. 

NetBeans – Michael's blog - August 18, 2016 05:08 PM
NetBeans Evening Cologne

On Sept. 9th 2016 the NetBeans Dream Team together with the Java User Group Cologne organize the first NetBeans Evening Cologne. From 6 pm till 9 pm you’ll get an evening full with latest information about NetBeans and Java. Meet the newest new features in NetBeans IDE, see the NetBeans roadmap, learn about features related … Continue reading "NetBeans Evening Cologne"

Geertjan's Blog - August 18, 2016 06:09 AM
Sign Up Free, Today: Oracle JET MOOC

A lot of work has gone into the preparation of something completely different—an enterprise JavaScript MOOC (massive open on-line course) via Oracle JET, which will start coming Monday, 22 August. Oracle JET is a set of best practices, recommendations, architectures, templates, and components for enterprise JavaScript applications.

There are over 1,000 subscribers to the MOOC so far. The MOOC will take 3 weeks of your time, the first week starting on Monday, 22 August. Each week is defined by one lesson, which is in 10 parts, each part consisting of a YouTube clip, each clip lasting no longer than about 10 minutes, together with self-study and homework assignments. Each of the two following weeks a new lesson will be made available. Each lesson ends with a quiz. Successful completion of all quizzes results in a certificate of completion. 

Lesson 1, entitled "Taking Off with Oracle JET", takes you on a tour of the reasoning behind Oracle JET and an exploration of its underpinnings. By the end of that lesson, you're able to create Oracle JET applications. You'll have learned about Oracle JET modules, components, and layouts. You'll have a really great basis for creating enterprise JavaScript applications. Lesson 2, entitled "Exploring the Skies with Oracle JET", gives you a structured approach to learning from the Oracle JET Cookbook, which is filled with a range of enterprise components, e.g., graphs and tables, and shows you how to use them and integrate them into your Oracle JET applications. Lesson 3, entitled "Into the Clouds with Oracle JET", shows you how to integrate with the world around Oracle JET, i.e., 3rd party components, internationalization, accessibility, security, etc.

Want to get a quick feel for how the MOOC will be? Part 1 (of 10 parts, which will be released next week) of the first lesson is already available:

&amp;lt;span id=&amp;quot;XinhaEditingPostion&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;

Sign up here!

NetBeans – Michael's blog - August 16, 2016 04:02 PM
Secure passwords

Because the access to special areas of Alumni (an application described in my book “Web Development with Java and JSF”) shall be restricted to members only, we need to restrict the access to authorized persons only. During the registration process, we ask the user to enter a password. This part is yet missing in the … Continue reading "Secure passwords"

Adam Bien - August 16, 2016 12:05 PM
Angular 2: Styling The Generated Host Tag

Angular 2 replaces / generates a "synthetic" tag for each component without any styling with the name specified in the selector

The component below:


import { Component } from '@angular/core';
@Component({
  selector: 'hello-app',
  template: '<h1>Styling the host component</h1>',
})
export class AppComponent { }

generates the following markup:

<hello-app>
 <h1>Styling the host component</h1>
</hello-app>

Additional styling of the "host" tag can be added with the host object:


import { Component } from '@angular/core';
@Component({
  selector: 'hello-app',
  template: '<h1>Styling the host component</h1>',
  host: {"class":"nice"}
})
export class AppComponent { }

which generates the following output:

<hello-app class="nice">
	<h1>Styling the host component</h1>
</hello-app>

Putting the selector into angle brackets: selector: '[hello-app]' searches for an attribute, not a tag, with the name of the selector, e.g.:


<div hello-app></div>

See you at Java EE Workshops at Munich Airport, Terminal 2 and particularly at Building Angular 2 Applications and Building React Applications.


Real World Java EE Workshops [Airport Munich]>

Geertjan's Blog - August 14, 2016 07:00 AM
What Are Your Favorite NetBeans Features?

What are your favorite NetBeans features? Damir Demirović from Serbia answers that question today in a new article on JAXenter. An extract:

Read the article here: https://jaxenter.com/netbeans/damir-demirovic-my-five-favourite-netbeans-features

Geertjan's Blog - August 12, 2016 07:00 AM
Code Sharing for NetBeans Developers!

Through the years, a recurring request by developers everywhere—not least among NetBeans users—is a facility for collaborative development. In a new article on JAXenter, I share info on two platforms for snippet sharing and how neatly they integrate into NetBeans IDE.

Some extracts: 

The full article: https://jaxenter.com/netbeans/code-sharing-for-netbeans-developers

markiewb's blog - August 11, 2016 06:56 PM
Quicktip: How to customize the names of Maven project nodes

Since NetBeans 7.4 you can configure the name of Maven-based project via options at “Tools|Options|Java|Maven|Appearance”. No additional plugin is required.

Mavenprojectnodenamecustomization

For other useful features have a look at the “New and Noteworthy” pages at http://wiki.netbeans.org/NewAndNoteWorthy


Geertjan's Blog - August 10, 2016 07:00 AM
Favorite NetBeans Features!

The full article is here on JAXenter: https://jaxenter.com/netbeans/yesaya-athuman-my-five-favorite-netbeans-features

Adam Bien - August 10, 2016 06:59 AM
Oracle on Java EE 8 News, Monitoring, Sonar Setup, BCE Entities or 29th airhacks.tv Questions and Answers

90 live attendees from all over the world (according to chat: France, Nigeria, Costa Rica, Netherlands (...)) participated in the 29th edition of airhacks.tv starting with the "Oracle and Java EE 8" discussion including press releases, then I answered questions ranging from Akka interoperability, over Java EE monitoring, to file access from EJBs and Sonar Setup:

Any questions left? Ask now and see your topic discussed at the first Monday of the month, 6 pm CET.

See you at Java EE Workshops at Munich Airport, Terminal 2 or Virtual Dedicated Workshops / consulting. Is Munich's airport too far? Learn from home: airhacks.io.


Real World Java EE Workshops [Airport Munich]>

Geertjan's Blog - August 09, 2016 10:28 AM
Learn Oracle JET in 3 Weeks

Oracle JET, the open source toolkit for enterprise JavaScript, targeted at mobile and web applications, was announced at JavaOne and OpenWorld last year. In February, it was open sourced at github.com/oracle/oraclejet. Soon you'll be able to take a free course on-line, which will introduce you to all the key topics and give you many exercises to do to guide you through the process of creating JavaScript enterprise applications in a simple and logical way:

Click here, to sign up, today!

NetBeans Ruminations » NetBeans - August 09, 2016 10:24 AM
JavaFX and NetBeans: Dynamically Loading Windows

The Swing-based window system in the NetBeans Platform has the concept of a window that is loaded at runtime. These windows derive from the class TopComponent and are registered using annotations, and are created using a handy wizard in the NetBeans IDE. Today I am going to show you how to do something similar with JavaFX components, using the default lookup of the NetBeans platform. My aim is to load an FXML file and display it on a tabbed pane.

I am using the source code from my previous blog entry as a starting point because I already had it handy. That main fxml file already had a tabPane, which is what I require in the GUI.

Window with basic menu

Application from the previous blog entry

I created a package called za.co.pellissier.javafxwindowsystem.api where the public API of my JavaFXWindowSystem will be located. To be able to add a component to the tabbed pane, the text to be displayed on the tab as well as a javafx.scene.Node object is needed. So I created an interface that windows will need to implement:

package za.co.pellissier.javafxwindowsystem.api;

import javafx.scene.Node;

public interface IJavaFXWindow {

    public Node load();

    String getWindowName();
}

There is a class called FXMLLoader that is able to load an fxml file and return a Node object representing its content. To save future implementers of this API some effort, here is an abstract class that handles the loading:

package za.co.pellissier.javafxwindowsystem.api;

import java.io.IOException;
import java.net.URL;
import java.util.logging.Level;
import java.util.logging.Logger;
import javafx.fxml.FXMLLoader;
import javafx.scene.Node;

public abstract class AJavaFXWindow implements IJavaFXWindow {
    
    private final String fxmlFileName;

    public AJavaFXWindow(String fxmlName) {
        fxmlFileName = fxmlName;
    }
    
    @Override
    public Node load() {
        try {
            URL resource = getClass().getResource(fxmlFileName);
            return (Node) FXMLLoader.load(resource);
        } catch (IOException ex) {
            Logger.getLogger(getClass().getName()).log(Level.SEVERE, null, ex);
        }
        return null;
    }
}

That is all that there is to the API, for now. :)

Note: Remember to export the package (set it to public) if you want it to be visible to other modules!

So lets look at how it is used by the window system. In my MainWindowController class (the JavaFX controller for the main fxml file), I added this method:

    private void loadWindows() {
        Collection<? extends IJavaFXWindow> windows = 
                Lookup.getDefault().lookupAll(IJavaFXWindow.class);
        for (IJavaFXWindow window : windows) {
            Node win = window.load();
            String name = window.getWindowName();
            tabPane.getTabs().add(new Tab(name, win));
        }
    }

I called this method in the initialize() method after the menu items are loaded.

All that remains is to see how a new window can be added to the system. First, lets create a new module called JavaFXTestWindow to contain the new window. It needs dependencies on Lookup API and JavaFXWindowSystem (the module where the API is defined).

In the JavaFXTestWindow module, I created a new fxml file called testwindow.fxml using SceneBuilder, and generated a controller class using the NetBeans IDE. Now for the most important step… implementing that brand new API!

package za.co.pellissier.testwindow;

import org.openide.util.lookup.ServiceProvider;
import za.co.pellissier.javafxwindowsystem.api.AJavaFXWindow;
import za.co.pellissier.javafxwindowsystem.api.IJavaFXWindow;

@ServiceProvider(service = IJavaFXWindow.class)
public class MyWindow extends AJavaFXWindow implements IJavaFXWindow {

    public MyWindow() {
        super("testwindow.fxml");
    }

    @Override
    public String getWindowName() {
        return "Test Me!";
    }
}

The most important line is the @ServiceProvider annotation – if you leave that out, the default lookup will not be able to find the window!

After cleaning and building, here is the result!

FXML file loaded

FXML file loaded

There are certainly still improvements to be made to this implementation. It only emulates a single mode in the NetBeans Platform Window System. And it requires the user to manually create an additional class. But it is a good start! :)

Adam Bien - August 09, 2016 05:57 AM
How to merge javax.json.JsonObject instances

Combining multiple javax.json.JsonObject instances requires copying their contents into a single JsonObjectBuilder instance:


@Test
public void merge() {
	JsonObject dev = Json.createObjectBuilder().
			add("developer", "duke").
			build();
	JsonObject lang = Json.createObjectBuilder().
			add("language", "java").
			build();

	JsonObjectBuilder result = Json.createObjectBuilder();
	dev.entrySet().forEach(s -> result.add(s.getKey(), s.getValue()));
	lang.entrySet().forEach(s -> result.add(s.getKey(), s.getValue()));
	JsonObject merged = result.build();
	assertThat(merged.getString("developer"), is("duke"));
	assertThat(merged.getString("language"), is("java"));
}

Adding additional attribute to a JsonObject instance works similarly.

See you at Java EE Workshops at Munich Airport, Terminal 2, particularly at: Effective Java EE 7! Is MUC too far? Checkout effectivejavaee.com


Real World Java EE Workshops [Airport Munich]>

DukeScript - August 08, 2016 11:46 PM
Big Data with DukeScript

At the JCrete conference last week we had some DukeScript hacking sessions, and we were was asked for best practices when you have large data sets to display in a grid. One solution is paging. If you want to load all the data at once, here’s another solution.

Let’s assume we have a model like this:

@Model(className = "BigData", targetId = "", properties = {
    @Property(name = "values", type = Row.class, array = true)
})
final class DataModel {

    @Model(className = "Row", properties = {
        @Property(name = "firstName", type = String.class)
    })
    public static class RowVMD {
    }
}

The first thing you can do in order to improve performance is to check if your table data needs to be mutable. Very often it’s an easy win to add a simple attribute to your tabular data:

@Model(className = "BigData", targetId = "", properties = {
    @Property(name = "values", type = Row.class, array = true)
})
final class DataModel {

    @Model(className = "Row", properties = {
        @Property(name = "firstName", type = String.class, mutable=false)
    })
    public static class RowVMD {
    }
}

This “mutable=false” will create a plain value instead of an Observable and thus save memory and construction time. It makes sense even if you want to edit the data in the table. (You would then create also a mutable version of “Row”, copy the data of the selected element to this “EditableRow”, edit it, and replace the old Row in the BigData ViewModel with an updated new one).

But the main problem with displaying large datasets is a slow UI. If you want to, for example, display a table with 100.000 rows, your DOM will get really big and this will kill performance.

One way to deal with that is to “virtualize” your table. That means the table will behave as if it actually has 100.000 rows, while it only displays the 20 rows that are currently visible. The best way to model that in DukeScript is to register a custom component like this:

ko.components.register('big-table', {
    viewModel: function (params) {
        var self = this;
        self.originalValues = params.value;
        self.firstIndex = ko.observable(0);
        self.numVisible = ko.observable(0);
        this.visibleRows = ko.computed(function () {
            var visibleValues = self.originalValues().slice(self.firstIndex(), self.firstIndex() + self.numVisible() + 1);
            return visibleValues;
        });
    },
    template: {element: 'big-table-template'}
});

A component consists of a ViewModel and a template. Our ViewModel has only four properties, the original values of our BigData object, the index of the first visible row, and the number of visible rows. The fourth is a computed property derived from the other three. It contains the values of the rows that are currently visible.

The template is loaded from an element in the page. This way we can modify the layout when we add more properties, or if we e.g. want to switch from a table to a list. Here’s a simple example:

<script id="big-table-template">
    <div
        data-bind = 'scroll: $data'
        style='height: 100px; overflow-y: scroll;
        overflow-x: auto;
        position: relative;
        background: grey;'>
        <div class = 'scroll-dummy' style = 'height: 110px;' > < /div>
            <div class = 'big-table-table' data-bind = 'foreach: visibleRows' style = 'position: absolute; top: 0; left: 0; background: red;' >
                <div class = 'big-table-row' style = 'height: 50px;' > <span data-bind = 'text: firstName' ></span></div >
            </div>
            </script>

There’s a div that wraps everything. We can set a fixed height on it. In our case it’s 100px. It contains another div that acts as a “scroll-dummy”. The only purpose of this is to make the scrollbar behave as if we have lots of elements in our table. We’ll resize it later to match the height of all rows. On top of it there’s an element that wraps the rows. It can be a list, a table, or in this case, a simple div. It uses the foreach binding to display the visible rows.

Now we need to make this dynamic. You can use a custom binding for this. It calculates how many elements are visible and listens to scroll events in order to update the firstIndex property of our components ViewModel. And it moves our “big-table-table” to the view port of our virtualized control.

ko.bindingHandlers.scroll = {
    init: function (element, valueAccessor, allBindings, viewModel, bindingContext) {
        var self = this;
        self.element = element;
        self.viewModel = viewModel;
        var scrollDummy = self.element.getElementsByClassName('scroll-dummy')[0];
        self.table = self.element.getElementsByClassName('big-table-table')[0];
        var maxPos = self.element.offsetHeight;
        var els = self.element.getElementsByClassName('big-table-row');
        var rowHeight = els[0].offsetHeight;
        self.viewModel.numVisible(maxPos / rowHeight);
        scrollDummy.style.height = rowHeight * self.viewModel.originalValues().length + "px";
        self.firstIndex = viewModel.firstIndex();
        self.viewModel.firstIndex.subscribe(function (newValue) {
            var scrollTop = self.element.scrollTop;
            if (self.firstIndex > newValue) {
                scrollTop -= rowHeight;
            }
            self.table.style.top = (scrollTop < 0 ? 0 : scrollTop) + "px";
            self.firstIndex = newValue;
        });
        self.element.addEventListener('scroll', function (e) {
            var scrollTop = self.element.scrollTop;
            self.viewModel.firstIndex(Math.floor(scrollTop / rowHeight));
        });
    }
};

As a result, you will only have DOM nodes for the nodes that are currently visible and a nice and responsive UI.

In order to make this work, you will need to register the custom binding and custom component. I’ve put them together in a file called “bigtable.js” and register them like this:

@JavaScriptResource("bigtable.js")
public final class BigTableBinding {
    private BigTableBinding() {
    }
    
    @JavaScriptBody(args = {}, body = "")
    public static native void init();
    
}

Now you only need to make sure you call the init method before you bind the data:

static void onPageLoad() throws Exception {
        ui = new BigData();
        Models.toRaw(ui);
        BigTableBinding.init();
        for (int i = 0; i < 1000; i++) {
            ui.getValues().add(new Row("index " + i));
        }
        ui.applyBindings();
    }

Enjoy coding DukeScript!

Geertjan's Blog - August 08, 2016 10:06 AM
Most Unique Feature of NetBeans IDE!

What's NetBeans all about, what makes it special, why would anyone use NetBeans rather than something else, what are its key features, what distinguishes NetBeans from other tools, etc etc etc. Set aside those questions for a moment and take a look at this photo taken last week at JCrete:

That's a small part of the NetBeans community around the world, most of the above are members of the NetBeans Dream Team. And the enthusiasm that jumps out at you is why NetBeans is special. Yes, the Maven integration in NetBeans is awesome; yes, NetBeans makes working with Git a piece of cake; yes, if you're doing Java EE then NetBeans should really be your weapon of choice, etc etc etc. And NetBeans is also awesome when you build software on top of it.

But, beneath it all, is a group of fun people from all over the world—who have all kinds of different hobbies and interests, one of which is software development, which they all do in one way or another in/with/on NetBeans IDE.

In the pic, taken by Stephen Chin, are:

  • back row: Jose Pereda (Spain), John Kostaras (Greece), Paul Anderson (USA), Gail Anderson (USA), Jaroslav Tulach (Czech Republic), Kirk Pepperdine (Hungary), Sven Reimers (Germany), Timon Veenstra (Netherlands)
  • front row: Sven Ruppert (taking the place of Ivar Grimstad, who couldn't be found), Geertjan Wielenga (Netherlands), Toni "Crazy Screaming Guy" Epple (Germany), Zoran Sevarac (Serbia)

Adam Bien - August 08, 2016 09:03 AM
How to add an attribute to javax.json.JsonObject

Although javax.json.JsonObject implements Map<String, JsonValue> -- it is immutable. Any modification attempt results in UnsupportedOperationException:


    @Test(expected = UnsupportedOperationException.class)
    public void immutable() {
        JsonObject dev = Json.createObjectBuilder().build();
        dev.put("dev", JsonValue.NULL);
    }

To add a new attribute to an existing JsonObject instance, you will have to copy it's attributes into a JsonObjectBuilder instance, add any attributes and eventually build a new instance:

package com.airhacks.jsonp;

import javax.json.Json;
import javax.json.JsonObject;
import javax.json.JsonObjectBuilder;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
import org.junit.Test;

public class JsonTest {

    static final String STATUS_KEY = "status";

	
    @Test
    public void addAttributeToObject() {
        JsonObject dev = Json.createObjectBuilder().
                add("developer", "duke").
                build();
        String expected = "master";

        JsonObject devWithStatus = enrich(dev, STATUS_KEY, expected);
        assertThat(devWithStatus.getString(STATUS_KEY), is(expected));
        System.out.println(devWithStatus);
    }
	

    public JsonObject enrich(JsonObject source, String key, String value) {
        JsonObjectBuilder builder = Json.createObjectBuilder();
        builder.add(key, value);
        source.entrySet().
                forEach(e -> builder.add(e.getKey(), e.getValue()));
        return builder.build();
    }

}

See you at Java EE Workshops at Munich Airport, Terminal 2, particularly at: Effective Java EE 7! Is MUC too far? Checkout effectivejavaee.com


Real World Java EE Workshops [Airport Munich]>

Adam Bien - August 05, 2016 10:27 AM
Using Excel As Source For Unit Tests

Sophisticated business logic requires a high amount of high quality data for test purposes. Tabular data is easier maintainable in Excel then directly in Java code.

With Java 8 it is easy to provide a function which converts an Excel Row (actually a HSSF Row) into whatever POJO you like:


 Function pojoMapper() {
        return (row) -> {
            Iterator cells = row.cellIterator();
            return new Input(
                    asLong(cells.next()),
                    asLong(cells.next()),
                    asLong(cells.next()));
        };
    }


A few additional lines of code convert a Stream<Row> into a Stream<POJO>:


public static <T> Stream<T> load(Function<Row, T> mapper,...) {
        int skipCount = 0;
        if (hasHeader) {
            skipCount = 1;
        }
        String fileName = //...
        try (InputStream inp = new BufferedInputStream(new FileInputStream(fileName));) {
            try (XSSFWorkbook wb = new XSSFWorkbook(inp)) {
                XSSFSheet sheet = wb.getSheetAt(tab);
                Stream<Row> stream = StreamSupport.stream(sheet.spliterator(), false);
                return stream.skip(skipCount).map(mapper);

            }
        } catch (IOException ex) {
            throw new IllegalStateException("Problems processing file: " + fileName, ex);
        }
    }


Parameterized JUnit tests can be used to define the locations of excel files and load the sheets representing different use cases, test suites or regression tests.

Hence the code above is reusable, andit was extracted and released as: https://github.com/AdamBien/sheetfit/ (the pronunciation is semi-accidental :-)). This one-class utility is also available directly from maven central:

<dependency>
	<groupId>com.airhacks</groupId>
	<artifactId>sheetfit</artifactId>
	<version>0.0.1</version>
</dependency>


Example is implemented as system test: https://github.com/AdamBien/sheetfit/tree/master/sheetfit-st.

Also checkout javaeetesting.com or come to MUC: http://workshops.adam-bien.com/about-testing.htm


Real World Java EE Workshops [Airport Munich]>

Geertjan's Blog - August 04, 2016 07:00 AM
Interface-Driven Java Formatter

Today at JCrete, Dan North and others suggested a really cool feature—the ability to format a Java source file based on the interfaces that the Java source file is implementing. The "Ordering" formatting options for Java source files in NetBeans IDE are quite detailed by default:

However, the new interface-driven formatting options, which I am implementing in a new tab (since the tab above is pretty full and can't be extended externally via a plugin anyway), enable the interfaces of the implementing class to determine the ordering of class members:

Here's Dan's notes on the above options:

Here's the code providing the GUI above, as well as the registration-related code for plugging the GUI into NetBeans IDE:

https://github.com/GeertjanWielenga/InterfaceDrivenJavaFormatter.git

Now "all" that needs to be done is implement the logic behind the above GUI. Anyone is welcome to join in with this cool JCrete-driven feature! 

Adam Bien - August 02, 2016 04:39 AM
Sending An OPTIONS Request With Angular 2

The Angular 2 Http class does not offer an OPTIONS convenience method out-of-the box. Interestingly, all the major HTTP methods are supported: GET, POST, PUT, delete, patch and head, but the OPTIONS was not implemented. To perform an e.g. POST request, you can use the built-in method:


import { Http } from '@angular/http';
import 'rxjs/add/operator/toPromise';

export default class XYZService{
   
    constructor(private http:Http){}

    performPost(uri,payload):Promise<Workshop[]>{
        return this.http.post(uri,payload).
        toPromise().
        then(r => r.json()).
        catch(this.handleError);
    }

   handleError(error){
        return Promise.reject(error.messages || error);
    }
//(...)

For the initiation of an OPTIONS request you will have to rely on the generic request method of the same Http class:

    options(uri):Promise{
        return this.http.request(uri,{method:'OPTIONS'}).
        toPromise().
        then(r => r.json()).
        catch(this.handleError);
    }

See you at Java EE Workshops at Munich Airport, Terminal 2 and particularly at Building Angular 2 Applications or Building React Applications.


Real World Java EE Workshops [Airport Munich]>

Adam Bien - August 01, 2016 03:04 AM
Java EE 8 Plans, Oracles Statement, Performance Smoke, Software Quality Rules, Cross-Jars Alternatives or 29th airhacks.tv Questions and Answers

Questions for the 29th a airhacks.tv, Today (August, 1st) at 6pm CET (see archives):

  1. Java EE 8 news: semi-official Oracle plans for Java EE 8, JavaOne (discussion)
  2. Serving files without a WAR
  3. Java EE performance monitoring and results interpretation
  4. Software quality with Sonar and Java EE: rules, defaults and real world
  5. Accessing EJBs from EntityListener's
  6. Running "Server Smoke" on 141 Processors and 10 TB
  7. Cross-Jar @Alternative's
  8. Referencing Entity Manager from JPA Entities
  9. JAX-RS ExceptionMappers in internet-facing API
  10. EntityManager, serialization and clustering
  11. BCE: referencing JPA entities from other components

The questions above are going to be answered during the next "Airhacks Q & A" http://airhacks.io live. You can subscribe to the channel and / or for the next event: http://www.ustream.tv/channel/adambien (both is optional, no registration required to watch this event live).

If you still miss a question, ask at https://gist.github.com/AdamBien/48148f11f649dd756993a876f7354061, write a comment on this post, tweet your question with the hashtag "#airhacks" or mention me https://twitter.com/AdamBien.

See you at Java EE Workshops at Munich Airport, Terminal 2 or Virtual Dedicated Workshops / consulting. Is Munich's airport too far? Learn from home: airhacks.io.


Real World Java EE Workshops [Airport Munich]>

NetBeans Ruminations » NetBeans - July 26, 2016 09:55 PM
JavaFX and NetBeans Actions

I was asked some very good questions in response my post about the JavaFX makeover for the NetBeans Platform! Questions with long and interesting answers, questions that sparked more questions in my mind. So here is the first post in response to those questions. :)

Is it possible to reuse normal NetBeans Platform actions?

For the purpose of this exploration, I decided to create a simple NetBeans Platform application to work with. A newly created one, with all of the latest infrastructure available (including annotations for registration). With one action for use today, and one window for another post to follow. So, we start off with this little application:

Simple application to transform

Simple application to transform

The action that I created is registered using annotations:

@ActionID(
        category = "Edit",
        id = "za.co.pellissier.someaction.SomeAction"
)
@ActionRegistration(
        iconBase = "za/co/pellissier/someaction/clickme.png",
        displayName = "#CTL_SomeAction"
)
@ActionReferences({
    @ActionReference(path = "Menu/File", position = 1300),
    @ActionReference(path = "Toolbars/File", position = 200)
})
@Messages("CTL_SomeAction=Action!")
public final class SomeAction implements ActionListener {

At compile time, these annotations are transformed into entries in the generated layer file. And at run time that gets loaded into the System FileSystem. Most days, you would not need to know any of that to work with actions. But today is not most days… :)

If you look at the module project where the action was created in Files view (after cleaning and building the module), you will see the generated-layer.xml file:

Generated layer file

Generated layer file

Looking at the content of the generated layer file, we can see where the action will be registered at runtime:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE filesystem PUBLIC "-//NetBeans//DTD Filesystem 1.2//EN"
                            "http://www.netbeans.org/dtds/filesystem-1_2.dtd">
<filesystem>
    <folder name="Actions">
        <folder name="Edit">
            <file name="za-co-pellissier-someaction-SomeAction.instance">
                <!--za.co.pellissier.someaction.SomeAction-->
                <attr
                    bundlevalue="za.co.pellissier.someaction.Bundle#CTL_SomeAction" name="displayName"/>
                <attr
                    methodvalue="org.openide.awt.Actions.alwaysEnabled" name="instanceCreate"/>
                <attr name="delegate" newvalue="za.co.pellissier.someaction.SomeAction"/>
                <attr name="iconBase" stringvalue="za/co/pellissier/someaction/clickme.png"/>
                <attr boolvalue="false" name="noIconInMenu"/>
            </file>
        </folder>
    </folder>
    <folder name="Menu">
        <folder name="File">
            <file name="za-co-pellissier-someaction-SomeAction.shadow">
                <!--za.co.pellissier.someaction.SomeAction-->
                <attr name="originalFile" stringvalue="Actions/Edit/za-co-pellissier-someaction-SomeAction.instance"/>
                <attr intvalue="1300" name="position"/>
            </file>
        </folder>
    </folder>
    <folder name="Toolbars">
        <folder name="File">
            <file name="za-co-pellissier-someaction-SomeAction.shadow">
                <!--za.co.pellissier.someaction.SomeAction-->
                <attr name="originalFile" stringvalue="Actions/Edit/za-co-pellissier-someaction-SomeAction.instance"/>
                <attr intvalue="200" name="position"/>
            </file>
        </folder>
    </folder>
</filesystem>

An internet search for the system file system reveals this wiki page which gives us the hint that the FileUtil class is going to be a useful one. And finding usages of that class reveals the following interesting method in org.netbeans.core.windows.view.ui.MainWindow:

    private static JMenuBar getCustomMenuBar() {
        try {
            String fileName = Constants.CUSTOM_MENU_BAR_PATH;
            if (fileName == null) {
                return null;
            }
            FileObject fo = FileUtil.getConfigFile(fileName);
            if (fo != null) {
                DataObject dobj = DataObject.find(fo);
                InstanceCookie ic = (InstanceCookie)dobj.getCookie(InstanceCookie.class);
                if (ic != null) {
                    return (JMenuBar)ic.instanceCreate();
                }
            }
        } catch (Exception e) {
            Exceptions.printStackTrace(e);
        }
        return null;
    }

This method is a great and simple example of how to call instanceCreate() for an item registered on the file system. So together with the information from last time, we now have the pieces of information to start implementing the solution. This time I created a file called mainwindow.fxml (remember to update JavaFXWindowManager to load this file):

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.control.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>

<AnchorPane prefHeight="371.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="za.co.pellissier.javafxwindowsystem.MainWindowController">
   <children>
      <MenuBar fx:id="menuBar" prefHeight="25.0" prefWidth="600.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" />
      <TabPane fx:id="tabPane" layoutY="25.0" prefHeight="350.0" prefWidth="600.0" tabClosingPolicy="UNAVAILABLE" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="21.0" />
   </children>
</AnchorPane>

The easiest place to call the code that loads the menu items is in the initialize() method of the controller class. Note that some of the menus, like Window, causes a StackOverflowException when being loaded in this context. It happens because it in turn calls on the Window System that is being loaded. So for now, lets exclude those menus. I also created a layer file and removed some of the File menu actions (see below) for the same reason.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE filesystem PUBLIC "-//NetBeans//DTD Filesystem 1.2//EN" "http://www.netbeans.org/dtds/filesystem-1_2.dtd">
<filesystem>
    <folder name="Menu">
        <folder name="File">
            <file name="Separator3.instance_hidden"/>
            <file name="Separator4.instance_hidden"/>
            <file name="org-netbeans-modules-print-action-PageSetupAction.shadow_hidden"/>
            <file name="org-netbeans-modules-print-action-PrintAction.shadow_hidden"/>
            <file name="org-openide-actions-SaveAction.shadow_hidden"/>
            <file name="org-openide-actions-SaveAllAction.shadow_hidden"/>
            <file name="org-openide-actions-SaveAsAction.shadow_hidden"/>
        </folder>
    </folder>
</filesystem>

So here is the controller class that does the basics of loading the actions and adding them to the JavaFX GUI, after a lot of debugging and hunting for ways to access the user friendly names for the actions.

You will notice several TODOs in the code, and there are probably more things to implement that I haven’t thought of yet. But at least it will point you in the right direction.

public class MainWindowController implements Initializable {

    @FXML
    private MenuBar menuBar;
    @FXML
    private TabPane tabPane;

    /**
     * Initializes the controller class.
     */
    @Override
    public void initialize(URL url, ResourceBundle rb) {
        FileObject systemConfigFile = FileUtil.getSystemConfigFile("Menu");
        FileObject[] menus = systemConfigFile.getChildren();
        for (FileObject menu : menus) {
            // skip the menus that cause a StackOverflowException
            if (menu.getName().equals("Window") || menu.getName().equals("GoTo")
                    || menu.getName().equals("Edit") || menu.getName().equals("View")) {
                continue;
            }
            Menu newMenu = new Menu(menu.getName());
            menuBar.getMenus().add(0, newMenu);
            FileObject[] items = menu.getChildren();
            // TODO Load sub-menus with their own menu items
            for (FileObject item : items) {
                try {
                    DataObject dobj = DataObject.find(item);
                    InstanceCookie ic = (InstanceCookie) dobj.getCookie(InstanceCookie.class);
                    if (ic != null) {
                        Object instance = ic.instanceCreate();
                        if (instance instanceof ActionListener) {
                            ActionedMenuItem menuItem = new ActionedMenuItem((ActionListener)instance);
                            newMenu.getItems().add(menuItem);
                        } else if (instance instanceof JSeparator) {
                            // TODO Add logic to avoid two consecutive separators
                            newMenu.getItems().add(new SeparatorMenuItem());
                        }
                    }
                } catch (IOException | ClassNotFoundException ex) {
                    Exceptions.printStackTrace(ex);
                }
            }
        }
    }
    
    private static class ActionedMenuItem extends MenuItem
    {
        private final ActionListener listener;

        private ActionedMenuItem(ActionListener instance) {
            String displayName = "";
            if (instance instanceof AbstractAction) {
                displayName = ((AbstractAction) instance).getValue("displayName").toString();
            } else if (instance instanceof SystemAction) {
                displayName = ((SystemAction) instance).getName();
            }
            // TODO Deal with & and mnemonics
            setText(displayName);
            
            listener = instance;
            
            setOnAction(new EventHandler<ActionEvent>() {
                @Override
                public void handle(ActionEvent e) {
                    try {
                        SwingUtilities.invokeAndWait(new Runnable() {
                            @Override
                            public void run() {
                                // TODO Create proper action
                                listener.actionPerformed(null);
                            }
                        });
                    } catch (InterruptedException | InvocationTargetException ex) {
                        Exceptions.printStackTrace(ex);
                    }
                }
            });
        }
    }
}
Window with basic menu

Window with basic menubar