Integrating Stack Exchange and JIRA

Posted By Hoyt Summers Pittman

Introduction

We are working to get the Red Hat Mobile Application Platform (RHMAP for brevity) Open-Sourced as FeedHenry and have discussed the usual array of community support options : mailing-lists, IRC, GitHub, JIRA, etc. However, the community is already using Stack Overflow to ask questions and get help from one another.

This leads to a question though : how do we integrate Stack Overflow monitoring with our current workflows? Enter so-monitor, a simple node.js application to watch Stack Overflow for questions and track their status in a JIRA. The project creates a ticket when a question is asked using a tag we monitor and then will close the JIRA ticket when the question is marked as answered.

Setup of Development Environment

I decided to write the monitor as a Node.js application, and that I would use Visual Studio Code as my IDE. Being a Java developer I am used to many tooling features: intellisense, robust debugging, etc. Also being a Java developer I had heard that most of these things were just not as mature in the Node.js ecosystem. While I feel this is still true, VS Code and [Definitely Typed|http://definitelytyped.org/] have closed the gap significantly. If you are interested in learning more about this setup I suggest following MS’s blog post. It was very helpful to me.

Consuming the Stack Exchange API

The Stack Exchange API is pretty standard as far as RESTful APIs go. There is a public API that with a limited quota expands more once you get an API key. The biggest difficulty I had was with their filters concept. Basically in Stack Exchange sites you can create a filter for your API calls that lives on their servers and then reference it with a stable, public ID.

I used Moveo’s Stack Exchange API wrapper to access the API and it worked rather well.

JIRA’s black magic

For as simple as Stack Overflow was, JIRA was not. However, JIRA is 100% scriptable and you can configure it to respond to nearly any requirement you may have. Putting a question into JIRA was basically four steps

  • Create the ticket
  • Formatting the question as a issue
  • Tagging my team
  • Closing the issue when the question was answered.

To wrap the JIRA REST API I used steve’s node jira library.

The trickiest part of the process was keeping the issue and the question states in sync. I used a custom field to track the question id returned by the Stack Exchange APIs, but managing the state hit an unexpected snag.

JIRA uses a transitions metaphor for changing the state of a ticket. This means there isn’t a “close issue” API call, but instead you have to upload a “transition” object to the issue endpoint that defines which transition you wish the issue to have taken. This means that you have to either a) check the state of the JIRA issue, lookup a transition, and execute that one or b) create a “Any State” -> “Close” transition in JIRA and hard code that. I chose “b”. For more information I encourage you to read JIRA’s API docs. They are really good and it is a very different pattern than Stack Exchange uses.

Conclusion

While the Stack Exchange and JIRA APIs were the main meat of the monitor project, there were many small “learnings” I had above and beyond that. VS Code and typings is a wonderful JavaScript experience. Using Q promises and wrapping node calls in Promises with simple one liners made my main code much easier to follow. Node.js and the JavaScript ecosystem has come phenomenally far in four years and it is finally as productive as more “Enterprisey” technologies like .Net and Java.

Dec 12th, 2016

JRebel and WildFly Swarm in NetBeans

Posted By Hoyt Summers Pittman

I’m not a great company man; I use NetBeans instead of RedHat’s JBDS. However, I am at least a GOOD company man because I am using WildFly Swarm instead of Sprint Boot. I also use JRebel because I don’t like wasting my time waiting on my projects to build. The combination of the three, however, gave me quite a headache today.

First, NetBeans is the only IDE that gets Maven correct. A Maven project is almost always a valid NetBeans project without any extra configuration. On top of this NetBeans makes it very easy to configure custom Maven goals and map them to your standard IDE actions. Second, WildFly Swarm is an awesome project that is basically Spring Boot but with real, rightsized Java EE. It also has awesome Maven support and I can’t say enough good things about how it. Finally, JRebel should need no introduction. It hot deploys Java code to just about anything and makes the write -> run -> debug cycle as fast as it can be.

My problems began when I imported my Swarm project into NetBeans. NetBeans recognized the fact the project was a war file and offered to deploy it to my installed WildFly server instead of running the Swarm plugin’s run goal. I created a custom NetBeans action to run the Swarm goal. This worked perfectly and all that was missing was JRebel.

JRebel did not want to play nice with the Swarm run goal. I’m not sure why, but eventually I decided to give running the project using the maven exec goal and passing in the Swarm Main class. This worked, but NetBeans wasn’t loading JRebel right out of the box. Finally, I copied over the exec arguments from a working Jar project into my custom run goal and JRebel successfully started (with errors that don’t seem to matter). Hot deploy worked!

If you are wondering here is my configuration :

Execute Goals : process-classes org.codehaus.mojo:exec-maven-plugin:1.2.1:exec
Set Properties : exec.args=-Dexec.args=-Drebel.env.ide.plugin.version=6.5.1 -Drebel.env.ide.version=8.2 -Drebel.env.ide.product=netbeans -Drebel.env.ide=netbeans -Drebel.base=/home/summers/.jrebel -Drebel.notification.url=http://localhost:17434 -agentpath:/home/summers/netbeans-8.2/java2/griffin/lib/libjrebel64.so -classpath %classpath org.wildfly.swarm.Swarm
exec.executable=java

So with that all working my Project Properties looks like this :

screenshot-from-2016-10-14-23-06-42

Oct 14th, 2016

Implementing Chip-8

Posted By Hoyt Summers Pittman

It has been a hobby of mine to create a video game console, but we live in a world where anyone can buy a $35 Raspberry Pi and install every 8, 16, and 32 bit game on it. So I have focused more on how consoles and software work and are made than actually making one. As part of this I have actually implemented an emulator of sorts, “Chip-8”.

Chip 8 was not a game console, but instead it is a byte-code interpreter that was originally run on 8-bit computers in the 1970s. It is, however, a good beginners project. My implementation took about 2 weeks to program and test. I have had a lot of success with running roms I have found online, and I am documenting it to share as a learning project for people that want to learn more about emulation, low level programming, or just like programming.

Now, enjoy my demo :

Aug 5th, 2016

Undertow Websocket Client in Java SE

Posted By Hoyt Summers Pittman

Undertow is a web server written in Java by JBoss. It uses a very modular architecture which allows the developer to pick and choose features they need so it fits anywhere from a Java EE web-server (Wildfly) to being embedded in a JavaSE application (the topic of this blog). Actually, this post isn’t about a web server AT ALL! This post is about using Undertow’s web socket library in a Java FX application to allow a server to send real time messages.

I’ve been working on a side project to make managing my Github notifications easier. The general idea is that a server will record my notifications, apply basic filtering on them, and then show me notifications ranked “Low”, “Medium”, and “High” priority. The UI of this application will be provided by Java FX and run standalone on the user’s system. A brief demo can be found on YouTube.

I originally tried the WebSocket implementation by TooTallNate, but they wouldn’t work correctly in my situation. I settled on the Undertow implementation mostly because I work for RedHat and can harass the developers on internal channels; however, this wasn’t needed.

The Undertow page mostly deals with server to server communication and the only WebSocket client example I could find that spoke to my situation was in a single unit test. However, I was able to cargo cult most of a working project, but I need to learn more about Xnio.

WebSocketProvider

The first thing I had to do was configure a XnioWorker. This static block is mostly cargo culture so I would refer to the official Xnio site before putting this into production.

    private static XnioWorker worker;

    static {
        try {
            worker = Xnio.getInstance().createWorker(OptionMap.builder()
                    .set(Options.WORKER_IO_THREADS, 2)
                    .set(Options.CONNECTION_HIGH_WATER, 1000000)
                    .set(Options.CONNECTION_LOW_WATER, 1000000)
                    .set(Options.WORKER_TASK_CORE_THREADS, 30)
                    .set(Options.WORKER_TASK_MAX_THREADS, 30)
                    .set(Options.TCP_NODELAY, true)
                    .set(Options.CORK, true)
                    .getMap());
        } catch (IOException | IllegalArgumentException ex) {
            Logger.getLogger(WebsocketProvider.class.getName()).log(Level.SEVERE, null, ex);
            throw new RuntimeException(ex);
        }
    }

Next, I created a static method to create a WebSocketClient instance and connect to my server. Because I am using self signed certificates as part of testing, I implemented a method to create an appropriate socket.

    public static WebSocketChannel getWebsocketClient(URI serverURI, String bearerToken, EventBus bus) {
        try {


            WebSocketClient.ConnectionBuilder builder = WebSocketClient.connectionBuilder(worker, new DefaultByteBufferPool(false, 2048), serverURI);
            builder.setClientNegotiation(new WebSocketClientNegotiation(null, null){
                @Override
                public void beforeRequest(Map<string , List<String>> headers) {
                    headers.put("Authorization", Lists.newArrayList("bearer " + bearerToken));
                }
            });

            if ("wss".equals(serverURI.getScheme())) {
                setupSSLSocket(builder);
            }

            WebSocketChannel channel = builder.connect().get();
            channel.resumeReceives();

            channel.getReceiveSetter().set(new AbstractReceiveListener() {
                @Override
                protected void onFullTextMessage(WebSocketChannel channel, BufferedTextMessage message) throws IOException {
                    bus.post(UPDATE_NOTIFICATIONS);

                }

                @Override
                protected void onText(WebSocketChannel webSocketChannel, StreamSourceFrameChannel messageChannel) throws IOException {
                    super.onText(webSocketChannel, messageChannel); //To change body of generated methods, choose Tools | Templates.
                    bus.post(UPDATE_NOTIFICATIONS);
                }

                @Override
                protected void onError(WebSocketChannel channel, Throwable error) {
                    super.onError(channel, error);
                    Logger.getLogger(WebsocketProvider.class.getName()).log(Level.SEVERE, error.getMessage(), error);

                }
            });

            return channel;
        } catch (IOException | CancellationException ex) {
            Logger.getLogger(WebsocketProvider.class.getName()).log(Level.SEVERE, null, ex);
            throw new RuntimeException(ex);
        }

    }

There are three pieces of code to pay special attention to channel.resumeReceives();, the WebSocketClientNegotiation implementation and the AbstractReceiveListener implementation. The first is necessary to receive messages from the server (I don’t know why, can someone from Undertow shed some light). The second adds a Bearer token authorization header so the server can authenticate the user with KeyCloak. The last is the actual handler for messages from the server. Currently it posts the message to an EventBus that various components are subscribed to.

There we have it! A very VERY simple websocket client for my Java FX application. If you want to play with it you can find the server and client source codes on my GitHub.

Jul 10th, 2016
Next Page »