Thursday Aug 25, 2016

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.

Wednesday Aug 24, 2016

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:

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

Saturday Aug 20, 2016

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.

Friday Aug 19, 2016

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. 

Wednesday Aug 17, 2016

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:

Sign up here!

Sunday Aug 14, 2016

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

Friday Aug 12, 2016

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

Wednesday Aug 10, 2016

Favorite NetBeans Features!

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

Tuesday Aug 09, 2016

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!

Monday Aug 08, 2016

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)

Thursday Aug 04, 2016

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! 

Saturday Jul 23, 2016

Twitter, Codebird, and JavaScript

In my "bower.json" file, I have a dependency set like this:

"codebird-js": "2.6.0"

That enables Codebird to be installed.

Next, I went to apps.twitter.com and created a new application, so that I now have a Consumer Key (API Key) and a Consumer Secret (API Secret).

<script type="text/javascript">
    var cb = new Codebird;
    cb.setConsumerKey(
            "replace-with-consumer-key",
            "replace-with-consumer-secret");
    cb.__call(
            "search_tweets",
            "q=NetBeans",
            function (response) {
                var statuses = response.statuses;
                for (var i = 0; i < statuses.length; i++){
                    var status = statuses[i];
                    var screen_name = status.user.screen_name;
                    var text = status.text;
                    console.log(screen_name + ": " + text);
                } 
            }, true);
</script>

The point of this blog entry is really to come to a point where you can see how to parse Twitter. Above, in bold, is the code needed for that. Printed out into the console you'll now see names/texts of those who have tweeted about NetBeans.

Friday Jul 22, 2016

OAuth and Oracle JET

OAuth is an open protocol to allow secure authorization in a simple and standard method from web, mobile, and desktop applications. Oracle JET includes a helper library for working with OAuth, though not OAuth itself, i.e., Oracle JET does not ship with OAuth. Instead, it provides a helper class that helps you manage OAuth tokens and requests, rather than including the OAuth client libraries that are needed. Also, there is documentation for the OAuth helper library in the Oracle JET Developer Guide, in a chapter named Using oj.OAuth in Your Oracle JET Application.

In your "define" block, you need to include "ojs/ojmodel", since that's where the OAuth class is provided. The OAuth class provides the methods you can use to initialize the oj.OAuth object, verify initialization, and calculate the authorization header based on client credentials or access token.

Once you have included "ojs/model", you initialize "oj.OAuth", as described in the chapter, e.g.:

self.myOAuth = new oj.OAuth('X-Authorization');

When you use the Oracle JET Common Model, you'll find the "oj.Collection.extend" enables you to reference your "oj.OAuth" object. Also see the related JavaScript documentation:

http://www.oracle.com/webfolder/technetwork/jet/jsdocs/oj.OAuth.html

Here's all the code for a real "define" block that includes OAuth for working with Twitter. Take note of the bits in bold below, which are the statements relating to OAuth:

define(['ojs/ojcore', 
        'knockout', 
        'jquery', 
        'ojs/ojmodel', 
        'ojs/ojtable', 
        'ojs/ojcollectiontabledatasource'],
    function (oj, ko, $) {
        function HeaderViewModel() {
            var self = this;
            self.TweetCol = ko.observable();
            self.datasource = ko.observable();
            self.serviceURL = 'https://api.jublo.net/codebird/1.1/search/tweets.json';
            self.myOAuth = new oj.OAuth('X-Authorization');
            self.parseTweet = function (response) {
                return {
                    id_str: response['id_str'],
                    text: response['text'],
                    userName: response['user']['name']
                };
            };
            var Tweet = oj.Model.extend({
                urlRoot: self.serviceURL,
                parse: self.parseTweet,
                idAttribute: 'id_str'
            });
            var myTweet = new Tweet();
            var TweetCollection = oj.Collection.extend({
                url: self.serviceURL + '?q=NetBeans',
                model: myTweet,
                oauth: self.myOAuth
            });
            self.getData = function () {
                self.datasource(null);
                self.TweetCol(new TweetCollection());
                self.myOAuth.setAccessTokenRequest(
                    JSON.parse(sessionStorage.getItem('credentials'))
                );
                self.TweetCol().fetch({
                    success: function () {
                        self.datasource(
                            new oj.CollectionTableDataSource(self.TweetCol())
                        );
                    },
                    error: function (jqXHR, textStatus, errorThrown) {
                        console.log('Error in fetch: ' + textStatus);
                    }
                });
            };
        }
        return new HeaderViewModel();
    }
);

In "main.js", the "credentials.js" file is loaded:

var prop;
$.ajax({
    url: 'js/credentials.json',
    dataType: 'json',
    async: false,
    success: function (data) {
        sessionStorage.setItem('credentials', JSON.stringify(data));
    },
    error: function (req, status, err) {
        console.log('something went wrong', status, err);
    }
});

The "credentials.js" file has this content:

{
    "client_id": "blabla",
    "client_secret": "blabla",
    "bearer_url": "https://api.jublo.net/codebird/oauth2/token",
    "access_token": "blabla"
}

Above, Codebird is used. Codebird is a library that is commonly used to manage OAuth2 connections to Twitter. And, instead of setting up your own code, you can use Codebird's proxy service.

In the "define" block above, notice the "self.getData" at the end, which ties everything together, and is called from the view:

<button data-bind="click: getData, 
                   ojComponent: { 
                       component: 'ojButton', 
                       label: 'Get Data'}">Get Data</button>
<hr>
<table 
    data-bind="ojComponent: {
            component: 'ojTable', 
            data: datasource,
	    columnsDefault: {headerStyle: 'text-align: left; white-space:nowrap;'}, 
            columns:
               [
                  {headerText: 'User ', field: 'userName'},
                  {headerText: 'Text', field: 'text'}
               ]}">
</table>

That's it. A complete sample scenario that uses OAuth with Oracle JET.

Thursday Jul 21, 2016

JBoss Data Virtualization with Oracle JET

I met with Cojan van Ballegooijen who is involved with the Red Hat JBoss Data Virtualization project. Read about that here:

http://www.jboss.org/products/datavirt/overview

I'm interested in setting up a scenario where Oracle JET could provide a dashboard on top of a VDB (virtual database).

Here's the steps we took to get started.

  1. We started by downloading the 6.3.0 Beta of JBoss Data Virtualization: http://developers.redhat.com/products/datavirt/download.

  2. After running "java -jar" on the JAR downloaded above, we had installed the product and had a folder named "EAP-6.4.0".

  3. In the folder "quickstarts/dynamicvdb-datafederation", there's a folder "src/teiidfiles", which we copied into the root, i.e., into the "EAP-6.4.0" folder.

  4. In the folder "standalone/configuration", there's a file named "standalone.xml", where we tweaked the reference to "jboss.dir" so that it pointed to the hardcoded location of the EAP-6.4.0 folder, i.e., there was a problem with slash escaping on Windows of the "jboss.dir" reference and to workaround that we hardcoded the path, for the data source with the jndi-name "java:/accounts-ds".

  5. Then we ran "bin/standalone.bat", the process started, the "teiidfiles" were loaded, and at this location we saw the JSON payload: http://localhost:8080/odata4/Portfolio/Accounts/CUSTOMER?$format=json

OK, great, we have the JSON, which provided the data from the VBD. Once we have JSON, the step to an Oracle JET dashboard is trivial, since Oracle JET has all kinds of hooks for working with JSON.

However, there's one stumbling block at this point and that is that authentication is needed for accessing our data. It seems that Keycloak is needed in this scenario:

https://access.redhat.com/documentation/en/red-hat-jboss-data-virtualization/6.3/security-guide/chapter-11-oauth-based-security-for-odata

That's the next step. Once that's done, then we have here a nice scenario for creating user interfaces on top of virtual databases created via JBoss Data Virtualization.

Tuesday Jul 19, 2016

Company Presentations on Oracle JET with NetBeans IDE

Today I spent some time with Oracle colleagues in presenting Oracle JET to a company in the Netherlands. The company was using a technology stack that included a front-end technology that needs to be modernized for various reasons and Oracle JET was presented to them as the way to bring the front-end of an application into the modern world of HTML5, CSS3, and JavaScript.

Of course, many small demos were done to make the key points of the benefits of Oracle JET. And those demos were all done in NetBeans IDE, with the great Oracle JET Support plugin!

Does your company want to modernize web front-ends? Take a look at Oracle JET, it's all open source and free, and available at http://github.com/oracle/oraclejet. We're doing company presentations on Oracle JET all over the world, if you're interested, let me know!

Thursday Jul 14, 2016

JSX in NetBeans IDE 8.2

JSX is a XML-like syntax extension to ECMAScript without any defined semantics. Many more details about it can be found here:

https://facebook.github.io/jsx/

JSX is popular in the React community which "recommend[s] using JSX because it is a concise and familiar syntax for defining tree structures with attributes. It's more familiar for casual developers such as designers." Many more details about that can be found here:

https://facebook.github.io/react/docs/jsx-in-depth.html

Many NetBeans IDE users have been asking for JSX support in NetBeans IDE, since they are using React:

https://netbeans.org/bugzilla/show_bug.cgi?id=250778

As you can see from the above, the NetBeans team has added parsing and lexing support for JSX over the past few days.

Let's take a look at the result, using this repo as an example project to try out JSX support in NetBeans IDE:

https://github.com/reactjs/react-tutorial

Here's what I see in a very (very very) recent NetBeans IDE build (click to enlarge the image):

Contrast the above to the same file opened in the current release of NetBeans IDE, i.e., NetBeans IDE 8.1, to see the difference:

Great news, isn't it? :-) At this point, don't expect extensive support for JSX or for React. However, as you can see above, at least you can now edit your files without there being error markings everywhere, which made NetBeans IDE impossible to work with when working with JSX.

Wednesday Jul 13, 2016

NetBeans Platform: An Ideal Platform for Scientific Computing

The session catalog for JavaOne 2016 is available here:

https://oracle.rainfocus.com/scripts/catalog/oow16.jsp?event=javaone&search.event=javaone

One of the entries you'll find there is this one: 

Interesting. A NetBeans Platform application that I had never heard of before. It looks like this:

And here's more info about it:

The above comes from here:

https://www.janelia.org/confocal-imagery-management-and-analysis-tools

I'm looking forward to attending this session at JavaOne this year! 

Tuesday Jul 12, 2016

Gallery Demos for JavaScript: Galleria.io

Following on from part 2, in this part we add Galleria.io to our set of dependencies in 'bower.json':

"dependencies": {
    "oraclejet": "2.0.2",
    "galleria": "1.4.2"
}

Here's the source code:

https://github.com/GeertjanWielenga/GalleriaDemos/tree/master/Galleria3-Galleria.io/app

The project structure is as follows:

Since Galleria.io is not an AMD module, we need to shim in the 'require.config':

shim: {
   'jquery': {
       exports: ['jQuery', '$']
   },
   'galleriaio': ['jquery']
}

The end result looks like this:

And, again, a Knockout component is created and used like this:

<div data-bind="component: {name:'galleria', 
    params: {
      uniqueID: '1',
      width: 300,
      height: 300,
      images: [
        'images/galleria1.jpg',
        'images/galleria3.jpg',
        'images/galleria4.jpg'
      ]
    }
}"></div>

Monday Jul 11, 2016

Gallery Demos for JavaScript: JQuery UI Accordion

Continuing from the first part, let's now move towards modularity via Require and data bindings via Knockout. 

Here is the application:

https://github.com/GeertjanWielenga/GalleriaDemos/tree/master/Galleria2-Knockout/app

The project structure is like this, which looks a lot like the structure of an Oracle JET application, though an Oracle JET template was not the starting point of the below. Instead, I started with a plain ordinary HTML/JavaScript application and built up the structure from there, i.e., as a normal JavaScript application:


Here the JQuery UI Accordion component is used, which looks as follows in this case: 

To make sure that the versions of the various libraries work together, instead of getting hold of JQuery, JQuery UI, Require, and Knockout separately, I'm getting hold of all of them at once via Oracle JET in 'bower.json':

"oraclejet": "2.0.2"

Each gallery makes use of a Knockout component created in the project, which is used as follows: 

<div data-bind="component: {name:'galleria', 
    params: {
      uniqueID: '1',
      images: [
        'images/galleria1.jpg',
        'images/galleria3.jpg',
        'images/galleria4.jpg'
      ]
    }
}"></div>

In the next part, we'll look at a different gallery component and set up the same kind of project structure to see how things work there.

Sunday Jul 10, 2016

Gallery Demos for JavaScript: PrimeUI Galleria

I'm looking at different image gallery components as examples of how to work with them in the context of Oracle JET. Also, these scenarios are example of how to migrate from non-Oracle JET applications to Oracle JET applications.

Here's the first, making use of the PrimeUI Galleria component:

https://github.com/GeertjanWielenga/GalleriaDemos/tree/master/Galleria1-Default/app

The structure of the application is like this: 


Here's how the component looks:

In the "bower.json" file, there is a single dependency:  

"primeui": "4.1.12"

In fact, this scenario is a plain normal JavaScript scenario that makes use of PrimeUI. No modularity, etc, just plain simple PrimeUI.

To get from the above scenario to an Oracle JET application, you'd need to include Require (for migration modularity) and Knockout (for migration to Knockout components and data bindings). That's the topic of the next blog entry.

About

Geertjan Wielenga (@geertjanw) is a Principal Product Manager in the Oracle Developer Tools group living & working in Amsterdam. He is a Java technology enthusiast, evangelist, trainer, speaker, and writer. He blogs here daily.

The focus of this blog is mostly on NetBeans (a development tool primarily for Java programmers), with an occasional reference to NetBeans, and sometimes diverging to topics relating to NetBeans. And then there are days when NetBeans is mentioned, just for a change.

Search

Categories
Archives
« August 2016
SunMonTueWedThuFriSat
 
1
2
3
5
6
7
11
13
15
16
18
21
22
23
26
27
28
29
30
31
   
       
Today