Fotolia_70774541_XS.jpg

Yea yea, I’m on a DB2 blog kick tonight. I’ve been a fan of DB2 for a long time and it’s about time I posted some of this!

What’s the goal?

Simple:

  • install DB2 (rootless)
  • configure it
  • configure fault monitors
  • setup autostart

That’s it!

What do I need?

This particular script assumes CentOS 7. To test it out, you can create a quick CentOS 7 VM, or spin up a droplet on DigitalOcean if you wish.

Note: make sure you have your host properly defined in /etc/hosts

Oh, and you should probably download DB2 Express-C while you’re at it.

Just get on with it!

Fine!

Ok, so a few points:

  • The script is a combination of @angoca‘s work on getting DB2 into Docker (https://github.com/angoca/db2-docker), and some of my own additions (like enabling the fault monitor).
  • The script must be run as root (which it will validate in lines 3-7)
  • The script will validate that you defined your hostname in /etc/hosts (lines 9-14)
  • This will be a rootless install, and the instance owner will be db2inst1
  • For testing, I like to make myself an instance owner (probably not best practice, but in the context of a development environment I’m fine with it) (line 23)
  • Lines 25-40 ensure needed packages are installed
  • Line 46 actually installs DB2
  • Lines 49-52 make some tweaks to the configuration (e.g. port, OS authentication, etc.)
  • Line 57 configures DB2 with our tweaks, and also enables TCP communication to the database
  • Lines 60-84 configure auto-start and the fault monitors
  • Lines 88-94 do some cleanup, then prompt to reboot

What do I do next?

With DB2 installed, all of my database user setup, database creation, table creation, etc. are all automated. Maybe in another post I’ll explain that.

Oh, and if you are using zsh, see my post on getting db2profile to work with zsh at http://www.craigstjean.com/2016/03/db2profile-and-zsh/

Are you a DBA and did I do something wrong? Let me know! I’ll get it fixed so I don’t direct someone the wrong way

Comment and share

db2profile and zsh

in DB2
Fotolia_52415534_XS.jpg

What?

To leverage DB2 commands from a *nix environment, you typically append the following to your shell profile script:

1
. /path/to/db2/sqllib/db2profile

But, if you try that in zsh, you get the lovely errors:

1
zsh: awk: command not found...
AddRemoveString:12: command not found: awk
zsh: sed: command not found...
AddRemoveString:14: command not found: sed
zsh: sed: command not found...
AddRemoveString:18: command not found: sed
zsh: awk: command not found...
AddRemoveString:12: command not found: awk
zsh: sed: command not found...
AddRemoveString:14: command not found: sed
zsh: sed: command not found...
AddRemoveString:18: command not found: sed
zsh: awk: command not found...
AddRemoveString:12: command not found: awk
zsh: sed: command not found...
AddRemoveString:14: command not found: sed
zsh: sed: command not found...
AddRemoveString:18: command not found: sed
zsh: awk: command not found...
AddRemoveString:12: command not found: awk
zsh: sed: command not found...
AddRemoveString:14: command not found: sed

And worse, you completely lost everything in $PATH. Due to differences between the Bourne shell and the Z shell, the AddRemoveString function in db2profile splits your path variables in a way it can’t recombine.

So how can I fix it?

Luckily, there’s an easy fix I’ve come up with. First, I copy db2profile to db2profile.zsh, then towards the bottom of AddRemoveString I add a line that replaces the newlines in the path variable with the correct delimiter:

In the end, it looks like this:

1
AddRemoveString()
{
    if [ $# -ne 3 ]; then
       return 0
    fi
    var=$1        #The enviornment variable to be processed
    addrm_str=$2  #The new path to be used
    action=$3     #Action: a -> add, r -> remove
    if [ "X${action?}" != "Xa" -a "X${action?}" != "Xr" ]; then
        return 0  # return without doing anything
    fi
    awkval='$1 != "'${addrm_str?}'"{print $0}'
    newval=`eval echo \\${$var:-""} | awk '{for (i=1; i<= NF; ++i) \
          if( $i != VAR && length($i) > 0 ) print $i":"}' FS=":" VAR=${addrm_str?}`
    newval=`echo ${newval?} | sed 's/\: /\:/g'`
    if [ "X${action?}" = "Xa" ]; then
        newval=${newval?}"${addrm_str?}"
    else
        newval=`echo ${newval?} | sed 's/:$//'`
    fi
+   newval=`echo ${newval?} | tr '\n' ':'`
    eval $var=\"${newval?}\"
    unset var addrm_str awkval newval
}

That line marked with a + is the line added (make sure to remove the + if you copy/paste).

Then, just update your .zshrc with:

1
. /path/to/db2/sqllib/db2profile.zsh

That’s it!

Comment and share

Fotolia_65716003_XS.jpg

What’s the problem?

I like to keep my system up to date, and I depend on many Homebrew packages on my OS X machine. Homebrew allows for this but I:

  • want it automated
  • want it to delete old versions that I am no longer using

How did I solve it?

First, I added this into my .zshrc (could be in your .profile if you use Bash):

1
function brew_update() {
    brew update
    brew upgrade --all
    ruby $HOME/remove_old_brews.rb
}

CURR_DATE=`date '+%Y-%m-%d'`
LAST_DATE=`head -n 1 $HOME/.brew_update_date 2>/dev/null`
if [ "$CURR_DATE" != "$LAST_DATE" ]; then
    echo $CURR_DATE > $HOME/.brew_update_date
    echo Updating Homebrew...
    brew_update
fi

Then, I created remove_old_brews.rb in my home directory:

Wait, what?!

Ok, first the shell will check the current date and compare it with a date stored in a .brew_update_date file. If they differ, it immediately updates the file (so I can open another Terminal while the update is in progress), then it calls brew_update.

brew_update tells Homebrew to update its index, then upgrade all out of date packages. Finally, brew_update calls remove_old_brews.rb

remove_old_brews.rb looks at all installed packages in /usr/local/Library/LinkedKegs and finds packages with more than 1 version installed. For those, it finds whichever ones are not the currently linked version and removes them.

Things to consider

This is tuned for my workflow, but yours may differ. What I wanted was:

  • update the first time I open Terminal in a day
    • meaning if I really need a Terminal, I can just open another and the 2nd one won’t update
  • keep what was updated at the front of my attention (which is why I didn’t just put it into cron)

And that’s about it.

Comment and share

Fotolia_76400607_XS.jpg

The Goal

Message Queues can be used for a vast amount of problems, from establishing worker processes to managing load on expensive resources. But, how can you effectively use WebSphere MQ with WebSphere Application Server? Let’s find out!

This tutorial assumes you already have WebSphere Application Server installed, and either have WebSphere MQ installed or have it accessible. If you still need WebSphere Application Server, click here to grab WebSphere Application Server for Developers. If you need WebSphere MQ, grab WebSphere MQ v8 for Developers from here.

The Example

To demonstrate this, we’ll start with a simple “Hello World” with a basic servlet and an MDB, then move to a full blown Spring application.

Preparing WebSphere MQ

To simply the tutorial, I am running WebSphere MQ locally. If you are going to leverage an instance that is already configured and running, just skip ahead.

I already have the mqm user and group, but I will add my user to the mqm group as well:

1
sudo usermod -a -G mqm craig

Next, I’ll create a new Queue Manager called TUTORIALQM and start the TCP listener. You can use MQExplorer to do this, or do the following:

1
newgrp mqm
/opt/mqm/bin/crtmqm -u DLQ TUTORIALQM
/opt/mqm/bin/strmqm TUTORIALQM
/opt/mqm/bin/runmqlsr -m TUTORIALQM -t TCP &

Creating the Queues for the Tutorial

To keep it simple, I’ll just start with two queues: REQ.HELLO and RESP.HELLO (for my Hello World requests and responses). You may choose to use MQExplorer to do this, or do the following:

queuedefs.conf
1
DEFINE QLOCAL ('REQ.HELLO') +
     REPLACE

DEFINE QLOCAL ('RESP.HELLO') +
     REPLACE
1
/opt/mqm/bin/runmqsc TUTORIALQM < queuedefs.conf

Preparing WebSphere Application Server

Now that the queues are ready to go, we can startup WebSphere and configure our queues.

Defining the Queue Connection Factory

  1. Launch the WebSphere Admin Console (typically http://localhost:9060/ibm/console)
  2. Expand Resources -> JMS -> Queue connection factories
  3. Adjust the Scope drop down to Server=server1
  4. Click New
  5. Select WebSphere MQ messaging provider and click OK
  6. Enter a name and a JNDI name, I will use HelloConnectionFactory and jms/HelloConnectionFactory
  7. Click Next
  8. Select “Enter all the required information into the wizard” and click Next
  9. Enter the Queue Manager name (TUTORIALQM) and click Next
  10. Enter the hostname and port for MQ (localhost, port 1414) and finish the wizard
  11. Save the WebSphere configuration

Defining the Queues

Next, we have to define the Queues within WebSphere:

  1. Expand Resources -> JMS -> Queues
  2. Adjust the Scope drop down to Server=server1
  3. Click New
  4. Select WebSphere MQ messaging provider, click OK
  5. Enter a name and JNDI name for the request queue, as well as the Queue name.
    I will use:
    • Name: Request_HelloQueue
    • JNDI Name: jms/Request_HelloQueue
    • Queue name: REQ.HELLO
  6. Click OK
  7. Click New and repeat for the response queue:
    • Name: Response_HelloQueue
    • JNDI Name: jms/Response_HelloQueue
    • Queue name: RESP.HELLO
  8. Save the WebSphere configuration

Defining the Activation Specification

Lastly, we need to define an Activation specification to invoke our Message-Driver Bean. Within the Admin Console:

  1. Expand Resources -> JMS -> Activation specification
  2. Adjust the Scope drop down to Server=server1
  3. Click New
  4. Select WebSphere MQ messaging provider, click OK
  5. Enter a name and JNDI name, I will use Activation_Hello and jms/Activation_Hello
  6. Click Next
  7. Enter the destination queue’s JNDI name (the request queue JNDI name we defined earlier, jms/Request_HelloQueue) and click Next
  8. Select “Enter all the required information into the wizard” and click Next
  9. Enter the Queue Manager name TUTORIALQM and click Next
  10. Enter the hostname and port for MQ (localhost, 1414) and complete the wizard
  11. Save the WebSphere configuration
  12. Restart WebSphere

A Basic Example Application

Before we get into a full application, let’s create a simple JSP + servlet and a Message-Driven Bean to demonstrate the basics.

To get started, create an EAR in Eclipse/RAD/RSA called BasicExample, a Dynamic Web Project called BasicExampleWeb, and an EJB Project called BasicExampleEjb (or clone my GitHub repository for the basic example and follow along).

Preparing the Web Application

First, we need to add our Queues and Connection factory to the IBM Web Binding XML file (ibm-web-bnd.xml in WEB-INF). The goal is to have our JNDI names available to the web resource, but allow us to change them in the application server if necessary.

  1. Open ibm-web-bnd.xml
  2. Click Add and select “Message Destination Reference”
  3. Enter jms/Request_HelloQueue into both Name and Binding Name
  4. Click Add and select “Message Destination Reference”
  5. Enter jms/Response_HelloQueue into both Name and Binding Name
  6. Click Add and select “Resource Reference”
  7. Enter jms/HelloConnectionFactory into both Name and Binding Name

Or, if you prefer XML:

ibm-web-bnd.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
<?xml version="1.0" encoding="UTF-8"?>
<web-bnd
xmlns="http://websphere.ibm.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://websphere.ibm.com/xml/ns/javaee http://websphere.ibm.com/xml/ns/javaee/ibm-web-bnd_1_2.xsd"
version="1.2">


<virtual-host name="default_host" />

<message-destination-ref name="jms/Request_HelloQueue" binding-name="jms/Request_HelloQueue" />
<message-destination-ref name="jms/Response_HelloQueue" binding-name="jms/Response_HelloQueue" />
<resource-ref name="jms/HelloConnectionFactory" binding-name="jms/HelloConnectionFactory" />
</web-bnd>

Next, we need to add them into web.xml:

  1. Open web.xml
  2. Click Add and select “Resource Reference” and configure:
    • Name: jms/HelloConnectionFactory
    • Type: javax.jms.QueueConnectionFactory
    • Authentication: Container
    • Sharing scope: Shareable
  3. Click Add and select “Message Destination Reference” and configure:
    • Name: jms/Request_HelloQueue
  4. Click “New Destination”
    • Name: jms/Request_HelloQueue
  5. Select jms/Request_HelloQueue in the list and click Next
  6. Configure as such:
    • Type: javax.jms.Queue
    • Usage: Consumes
  7. Click Finish
  8. Click Add and select “Message Destination Reference” and configure:
    • Name: jms/Response_HelloQueue
  9. Click “New Destination”
    • Name: jms/Response_HelloQueue
  10. Select jms/Response_HelloQueue in the list and click Next
  11. Configure as such:
    • Type: javax.jms.Queue
    • Usage: Consumes
  12. Click Finish

Or, if you prefer XML:

web.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" version="3.0"
xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">

<display-name>BasicExampleWeb</display-name>

<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>

<resource-ref>
<res-ref-name>jms/HelloConnectionFactory</res-ref-name>
<res-type>javax.jms.QueueConnectionFactory</res-type>
<res-auth>Container</res-auth>
<res-sharing-scope>Shareable</res-sharing-scope>
</resource-ref>
<message-destination-ref>
<message-destination-ref-name>jms/Request_HelloQueue</message-destination-ref-name>
<message-destination-type>javax.jms.Queue</message-destination-type>
<message-destination-usage>Consumes</message-destination-usage>
<message-destination-link>jms/Request_HelloQueue</message-destination-link>
</message-destination-ref>
<message-destination-ref>
<message-destination-ref-name>jms/Response_HelloQueue</message-destination-ref-name>
<message-destination-type>javax.jms.Queue</message-destination-type>
<message-destination-usage>Consumes</message-destination-usage>
<message-destination-link>jms/Response_HelloQueue</message-destination-link>
</message-destination-ref>
<message-destination>
<message-destination-name>jms/Request_HelloQueue</message-destination-name>
</message-destination>
<message-destination>
<message-destination-name>jms/Response_HelloQueue</message-destination-name>
</message-destination>
</web-app>

Preparing the EJB

First, we can just delete ejb-jar.xml, we don’t need it.

We do however want the ibm-ejb-jar-bnd.xml.

  1. Right click the EJB project
  2. Select Java EE Tools -> Generate WebSphere Bindings Deployment Descriptor

We cannot populate ibm-ejb-jar-bnd.xml with IBM’s tooling until after we’ve created the MDB, so let’s do that now.

  1. Right click the EJB project
  2. Select New -> Message Driven Bean (EJB 3.x)
  3. Configure the wizard as such:
    • Java package: com.craigstjean.mqtut.basic.mdb
    • Class name: HelloMDB
  4. Finish the wizard

Next, we can implement HelloMDB as such:

HelloMDB.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
package com.craigstjean.mqtut.basic.mdb;

import javax.annotation.Resource;
import javax.ejb.ActivationConfigProperty;
import javax.ejb.MessageDriven;
import javax.ejb.MessageDrivenContext;
import javax.ejb.TransactionAttribute;
import javax.ejb.TransactionAttributeType;
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.MessageProducer;
import javax.jms.Session;
import javax.jms.TextMessage;

/**
* Message-Driven Bean implementation class for: HelloMDB
*/

@MessageDriven(
activationConfig = { @ActivationConfigProperty(
propertyName = "destinationType", propertyValue = "javax.jms.Queue")
})
public class HelloMDB implements MessageListener {

@Resource
private MessageDrivenContext mdCtx;

@Resource(name = "jms/HelloConnectionFactory")
private ConnectionFactory connectionFactoryRef;

@Resource(name = "jms/Response_HelloQueue")
private Destination resourceDestRef;

/**
* Default constructor.
*/

public HelloMDB() {

}

/**
* @see MessageListener#onMessage(Message)
*/

@Override
@TransactionAttribute(TransactionAttributeType.REQUIRED)
public void onMessage(Message message) {
String name = null;
try {
// Retrieve request
name = ((TextMessage) message).getText();
} catch (JMSException e) {
e.printStackTrace();
mdCtx.setRollbackOnly();
}

try {
// Process request
String responseData = "Hello, " + name;

// Create and send response message
sendResponse(message, responseData);
} catch (JMSException e) {
e.printStackTrace();
// TODO error handling goes here
// consider producing a copy of the message onto a dead letter queue
// (the same way a message is produced onto the response queue, but without expiry)
mdCtx.setRollbackOnly();
} catch (Exception e) {
// NOTE: Do not allow the MDB the throw an exception or it will stop processing messages
e.printStackTrace();

// TODO error handling goes here
// consider producing a copy of the message onto a dead letter queue
// (the same way a message is produced onto the response queue, but without expiry)
}
}

private void sendResponse(Message requestMessage, String responseData) throws JMSException {
Connection jmsConnection = null;
Session session = null;

try {
jmsConnection = connectionFactoryRef.createConnection();
session = jmsConnection.createSession(false, Session.AUTO_ACKNOWLEDGE);

TextMessage responseMessage = session.createTextMessage();
// ! Set correlation id from our original message id
responseMessage.setJMSCorrelationID(requestMessage.getJMSMessageID());
responseMessage.setText(responseData);

MessageProducer mp = session.createProducer(null);
// use 30 minute expiry
mp.setTimeToLive(1000 * 60 * 30);
mp.send(resourceDestRef, responseMessage);
} finally {
try {
if (session != null) {
session.close();
}
} catch (JMSException e) {

}

try {
if (jmsConnection != null) {
jmsConnection.close();
}
} catch (JMSException e) {

}
}
}

}

As you can see, when a message comes in it simply takes the input, creates a response, and pushes the response onto the response queue. To tie the request queue to HelloMDB:

  1. Open ibm-ejb-jar-bnd.xml
  2. Click Add and select “Message Driven”
  3. Select HelloMDB and click Next
  4. Select “Resource Reference” and click Next
  5. Select “jms/HelloConnectionFactory” and click Next
  6. Enter a binding name of “jms/HelloConnectionFactory” and click Finish
  7. Select “Message Driven (HelloMDB)” and click Add
  8. Select “JCA Adapter” and click OK
    Configure as following:
    • Activation Spec Binding Name: jms/Activation_Hello
    • Destination Binding Name: jms/Request_HelloQueue
  9. Select “Message Driven (HelloMDB)” and click Add
  10. Select “Message Destination Reference” and click OK
  11. Select “jms/Response_HelloQueue” and click Next
  12. Enter a binding name of “jms/Response_HelloQueue”

In all, the resulting XML is:

ibm-ejb-jar-bnd.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?xml version="1.0" encoding="UTF-8"?>
<ejb-jar-bnd
xmlns="http://websphere.ibm.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://websphere.ibm.com/xml/ns/javaee http://websphere.ibm.com/xml/ns/javaee/ibm-ejb-jar-bnd_1_2.xsd"
version="1.2">


<message-driven name="HelloMDB">
<jca-adapter activation-spec-binding-name="jms/Activation_Hello" destination-binding-name="jms/Request_HelloQueue"/>
<resource-ref name="jms/HelloConnectionFactory"
binding-name="jms/HelloConnectionFactory" />

<message-destination-ref
name="jms/Response_HelloQueue"
binding-name="jms/Response_HelloQueue" />

</message-driven>
</ejb-jar-bnd>

Finishing the Web Application

With our MDB complete, all we need to do is update the web application to take a name, post a message onto the request queue, wait for a response, then return it to the user.

It’s not pretty, but it demonstrates the point:

index.jsp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<!DOCTYPE HTML><%@page language="java"
contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>

<html>
<head>
<title>index</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
</head>
<body>
<form action="servlet/hello" method="POST">
<div>
Name:
<input type="text" name="name">
</div>
<div>
<input type="submit">
</div>
</form>

<div>
${message}
</div>
</body>
</html>
HelloServlet.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
package com.craigstjean.mqtut.basic.servlet;

import java.io.IOException;

import javax.annotation.Resource;
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.MessageProducer;
import javax.jms.Session;
import javax.jms.TextMessage;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet(urlPatterns = "/servlet/hello")
public class HelloServlet extends HttpServlet {
private static final long serialVersionUID = -8211165987639677828L;

@Resource(name = "java:comp/env/jms/HelloConnectionFactory")
private ConnectionFactory connectionFactory;

@Resource(name = "java:comp/env/jms/Request_HelloQueue")
private Destination requestQueue;

@Resource(name = "java:comp/env/jms/Response_HelloQueue")
private Destination responseQueue;

@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String name = req.getParameter("name");

Connection jmsConnection = null;
Session session = null;

String response = null;
try {
jmsConnection = connectionFactory.createConnection();
session = jmsConnection.createSession(false, Session.AUTO_ACKNOWLEDGE);

TextMessage requestMessage = session.createTextMessage();
requestMessage.setText(name);

MessageProducer mp = session.createProducer(null);
// use 30 minute expiry
mp.setTimeToLive(1000 * 60 * 30);
mp.send(requestQueue, requestMessage);

String messageSelector = "JMSCorrelationID='" + requestMessage.getJMSMessageID() + "'";
MessageConsumer mc = session.createConsumer(responseQueue, messageSelector);
jmsConnection.start();

Message responseMessage = mc.receive(5 * 1000);
if (responseMessage != null) {
response = ((TextMessage) responseMessage).getText();
} else {
response = "No message found within 5 seconds...";
}

req.setAttribute("message", response);
req.getRequestDispatcher("/index.jsp").forward(req, resp);
} catch (JMSException e) {
e.printStackTrace();
} finally {
try {
if (session != null) {
session.close();
}
} catch (JMSException e) {

}

try {
if (jmsConnection != null) {
jmsConnection.close();
}
} catch (JMSException e) {

}
}

}

}

Up Next

Now that the basic example is complete, my next post will be a more fully fledged application!

Comment and share

Fotolia_55771234_XS.jpg

But Why?!

Most simply, WordPress just wasn’t the tool for what I needed.

My Requirements

  • Write locally, then push to the server
  • Markdown or Textile
  • Easy backup strategy
  • Performant
  • Maintain existing comments

Write locally, then push to the server

Writing locally means I don’t have to worry about sessions, exposing an admin section of my site that could be compromised, etc. Additionally, it means I can use Git and put my blog under source control.

Markdown or Textile

Self explanatory

Easy backup strategy

With WordPress an export gives you the content, but you also need to make sure you have a backup strategy for your database, images, etc.

Putting my blog in Git with a static generator means my source is my backup. Should someone ever hack my site, I just change my password and push again.

Performant

Self explanatory. You can’t get any faster than statically generated pages, even with WordPress cache plugins (which surprised me, they still seemed slow).

Maintain existing comments

Luckily my comments are already hosted via Disqus, so I simply needed to make sure whatever my solution would be could reference my existing post comments.

The Solution

Hexo! To get started, I just exported my site out of WordPress and imported into Hexo with hexo-migrator-wordpress.

Then, I downloaded all of my WordPress images and placed them into the posts’ asset folders. To use them, change the image references to {% asset_img image_name.png %}

Additionally, my previous code blocks were pretty messed up, so I replaced them with:
{% codeblock FILENAME lang:LANGUAGE %} ... {% endcodeblock %}

Next, I had issues with my image links. Where I wanted to do something like this:

1
{% asset_link full-image.png {% asset_img small-image.png %} %}

Instead I had to use traditional markdown, like this:
1
[![Title](full/path/to/small-image.png)](full/path/to/large-image.png)

The theme I went with (Tranquilpeak) supports both Google Analytics and Disqus, so I simply updated the _config.yml, then in each of my existing posts I added a disqusIdentifier frontmatter that matched my old posts.

And with all of that, here we are! Luckily without too many posts already it wasn’t too much work.

Comment and share

spring-boot

As Spring continues to evolve, it’s capabilities become more and more attractive to use. Checkout this great article by David Parish on using Spring Boot with WebSphere!

Spring Boot is a wonderful tool for creating rich powerful applications with a limited amount of code or complexity. It can optionally include Spring Data with JPA support. The Spring abstraction layer for JPA makes creating database independent applications a snap. The problem is that it uses JPA 2.1 features which WebSphere 8.5.5 does not support.

Comment and share

Fotolia_81329697_XS_T.png

Some Background

WebSphere controls whether applications (EARs and WARs) are in PARENT_FIRST or PARENT_LAST classloading mode by its deployment.xml. RAD, or Rational Application Developer, has tools to generate this, as does the application server itself, but the Eclipse plugins do not at the time of this writing. So how do you configure your applications?

Wait, what does the classloading mode do?

Simply, when your application attempts to load a class, say IOUtils from Apache Commons IO, the JVM needs to know what to do when it finds multiple classes with the same fully qualified name. You could have classes provided by your application server, global JARs that you have put into your application server, and JARs in your application.

_PARENT_FIRST _classloading means take classes found in WebSphere (the parent), or global JARs first. So if you bundle a version of Apache Commons IO that doesn’t match the parent version, your application will run with the parent version instead of your application’s version.

_PARENTLAST classloading means prefer your application’s first.

So what’s the problem?

Imagine this scenario:

  • Your servers have global JARs setup that specific applications running in the same WebSphere profile require
  • You start a new application in your local development environment and you don’t realize the server has overridden certain JARs
  • You bundle newer versions of those JARs in your application
    So, with the “It works on my machine” stamp of approval you push to your servers only to find… failure.

There are plenty of other scenarios that could lead to an issue as well.

What’s the silver bullet?!

Unfortunately, there is no silver bullet. You may want to re-evaluate having shared libraries, update their versions, change the classloading mode of your application, or use a different WebSphere profile. The right answer really depends on your environment, but if changing the classloading mode is right for you, read on!

Changing the classloading mode

There are a few ways to make this change:

  • Deploy your application to WebSphere and update the configuration in the admin console (or wsadmin)
  • Use RAD (Rational Application Developer) to change it, if you have RAD
  • Or, use a new tool that I’ve created!

Generating deployment.xml in WebSphere

To obtain a deployment.xml from WebSphere:

  1. Build your application as an EAR
  2. Manually install it to WebSphere (via your admin console at http://localhost:9060/ibm/console for example)
  3. Open your application in the admin console and configure your EAR’s classloader mode
  4. Use Manage Modules to configure the WARs’ classloader modes
  5. Save your changes to WebSphere
  6. Export your application from the admin console as an EAR
  7. Copy its ibmconfig with deployment.xml deeply nested in it

Generating deployment.xml in RAD

Generating deployment.xml in RAD is much easier:

  1. Right click your EAR
  2. Go to Java EE -> Open WebSphere Application Server Deployment
  3. Scroll to the bottom and configure classloader settings as desired

Comparing WebSphere’s generated deployment.xml to RAD’s

Updating the configuration in WebSphere generates a deployment.xml that you may not want to re-use. Let’s take a look at the differences:

WebSphere’s version

deployment.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
<?xml version=“1.0” encoding=“UTF-8”?>
<appdeployment:Deployment xmlns:appdeployment=“http://www.ibm.com/websphere/appserver/schemas/5.0/appdeployment.xmixmlns:xmi=“http://www.omg.org/XMIxmi:version=“2.0” xmi:id=“Deployment_1428026415557”>
<deployedObject xmi:type=“appdeployment:ApplicationDeployment” xmi:id=“ApplicationDeployment_1428026415557” deploymentId=“0” startingWeight=“1” binariesURL=“$(APP_INSTALL_ROOT)/WIN-F8QH15674T8Node02Cell/JpaExample.earuseMetadataFromBinaries=“false” enableDistribution=“true” createMBeansForResources=“true” reloadEnabled=“false” appContextIDForSecurity=“href:WIN-F8QH15674T8Node02Cell/JpaExamplefilePermission=“..dll=755#..so=755#..a=755#..sl=755” allowDispatchRemoteInclude=“false” allowServiceRemoteInclude=“false” asyncRequestDispatchType=“DISABLED” standaloneModule=“false” enableClientModule=“false”>
<targetMappings xmi:id=“DeploymentTargetMapping_1428026415557” enable=“true” target=“ServerTarget_1428026415557” />
<modules xmi:type=“appdeployment:WebModuleDeployment” xmi:id=“WebModuleDeployment_1428026415557” deploymentId=“1” startingWeight=“10000” uri=“JpaExampleWeb.war” classloaderMode=“PARENT_LAST” containsEJBContent=“0”>
<targetMappings xmi:id=“DeploymentTargetMapping_1428026415558” target=“ServerTarget_1428026415557” />
<classloader xmi:id=“Classloader_1428026415558” />
</modules>
<classloader xmi:id=“Classloader_1428026415557” mode=“PARENT_LAST” />
<properties xmi:id=“Property_1428026415557” name=“metadata.complete” value=“false” />
</deployedObject>
<deploymentTargets xmi:type=“appdeployment:ServerTarget” xmi:id=“ServerTarget_1428026415557” name=“server1” nodeName=“WIN-F8QH15674T8Node02” />
</appdeployment:Deployment>

RAD’s version:

deployment.xml
1
2
3
4
5
6
7
<?xml version=“1.0” encoding=“UTF-8”?>
<appdeployment:Deployment xmlns:appdeployment=“http://www.ibm.com/websphere/appserver/schemas/5.0/appdeployment.xmixmlns:xmi=“http://www.omg.org/XMIxmi:version=“2.0” xmi:id=“Deployment_1423511656329”>
<deployedObject xmi:type=“appdeployment:ApplicationDeployment” xmi:id=“ApplicationDeployment_1423511656329” startingWeight=“10”>
<modules xmi:type=“appdeployment:WebModuleDeployment” xmi:id=“WebModuleDeployment_1423511656329” startingWeight=“10000” uri=“JpaExample.war” classloaderMode=“PARENT_LAST” />
<classloader xmi:id=“Classloader_1423511656329” mode=“PARENT_LAST” />
</deployedObject>
</appdeployment:Deployment>

The differences

Primarily, the WebSphere version includes node/cell specifics. If you take that version and deploy to a different server, you will end up with new folders in your profile/installedApps directory. This doesn’t cause any issues (that I’ve experienced) but its annoying.

A better solution for non-RAD users

If you take a look at the RAD version, its pretty basic and just lists the applications deployed and which classloading mode they are in. The ids are a standard format with the time after them.

So, assuming you are not using anything else in deployment.xml, this file is easy to reproduce! And to make it easier, I created a command line application to do it for you!

https://github.com/craigstjean/WebSphere-Deployment-Xml-Tool

To use it, invoke the JAR, passing it your application.xml as the first parameter, followed by either:

  • Nothing (which shows you its menu)
  • list (lists the EAR and all web application’s classloading mode)
  • set parent first (sets the EAR and all web applications to PARENT_FIRST)
  • set parent last (sets the EAR and all web applications to PARENT_LAST)
    For example:
1
java -jar WebSphere-Deployment-Xml-Tool.jar C:\workspace\MyProject\MyEar\META-INF\application.xml set parent last

And that’s it!

If you have any troubles with it, please create a GitHub issue and I’ll take a look!

Comment and share

Cloud security

Some Background

I keep a private development server (on DigitalOcean) running FreeBSD. None of the users have passwords, I only use certificate based authentication to get in.

Ever since I first heard of Duo (https://www.duosecurity.com/product) I’ve wanted to integrate it into some of my projects. I figured hey, why not start with my dev server!

Getting Started

Honestly, Duo has done an amazing job at making the process extremely easy.

First, create your free account at https://signup.duosecurity.com/.

In the process, you will want to download their app to your phone (if you want to use push notifications, otherwise you can use SMS).

After you have followed the wizard, you are ready to integrate it into your system, your application, or whatever else you want.

Integrating Duo with FreeBSD

After signing into the Duo administrative dashboard, simply create a new Integration and choose UNIX Integration. Then, at the top of the page click the Duo Unix documentation and follow the guide. Consistent with everything Duo has done so far, it is both thorough and clear.

I chose only to integrate Duo with SSH, not with PAM. So for me I simply had to:

  1. Download duo_unix (https://dl.duosecurity.com/duo_unix-latest.tar.gz)
  2. Compile and install it
  3. Configure /etc/duo/login_duo.conf with the keys generated on your integration page
  4. Execute /usr/sbin/login_duo to test the configuration
  5. Add this to my sshd_config:
    ForceCommand /usr/sbin/login_duo

    That’s it! Now I login to my server with my SSH key, approve the login on my phone, and I’m good to go!

I’ve chosen to configure login_duo.conf to automatically choose push notifications (as opposed to SMS or phone call), and also configured it to only be enabled from the wheel group. For reference, here is my configuration:

[duo]
; Duo integration key
ikey = ***
; Duo secret key
skey = ***
; Duo API host
host = ***
; Send command for Duo Push authentication
pushinfo = yes
group = wheel
autopush = yes
prompts = 1

What’s Next?

Next, I might choose to integrate Duo with PAM (documented in the same integration guide), add it to WordPress, add it to my own applications, who knows?! Either way, I’m certainly impressed with what Duo has come up with.

Comment and share

Fotolia_69777853_XS-300x225.jpg

Getting Spring and Hibernate to place nice with WebSphere via JPA is an adventure in trial and error. In this post, I will guide you through what you need to make it work!

Just want the code? Head over to my GitHub at https://github.com/craigstjean/WebSphere-JPA-Spring-Hibernate

WebSphere 8.5 Users

Before we get started: WebSphere 8.5 supports JPA 2.0, not JPA 2.1. Be careful not to grab Hibernate JARs for JPA 2.1.

Obtaining Dependencies and Initial Setup

First thing’s first, I grabbed the following dependencies:

  • Hibernate 4.2.17.Final

    • lib/jpa/hibernate-entitymanager-4.2.17.Final.jar
    • lib/required/antlr-2.7.7.jar
    • lib/required/dom4j-1.6.1.jar
    • lib/required/hibernate-commons-annotations-4.0.2.Final.jar
    • lib/required/hibernate-core-4.2.17.Final.jar
    • lib/required/javassist-3.18.1-GA.jar
    • lib/required/jboss-logging-3.1.0.GA.jar
    • WARNING: Do not take the following JARs, they conflict with the APIs built in to WebSphere:

      *   lib/required/hibernate-jpa-2.0-api-1.0.1.Final.jar
      
      • lib/required/jboss-transaction-api_1.1_spec-1.0.1.Final.jar
  • Spring 4.1.6.RELEASE

    • aopalliance-1.0.jar
    • commons-codec-1.10.jar
    • spring-aop-4.1.6.RELEASE.jar
    • spring-beans-4.1.6.RELEASE.jar
    • spring-context-4.1.6.RELEASE.jar
    • spring-context-support-4.1.6.RELEASE.jar
    • spring-core-4.1.6.RELEASE.jar
    • spring-expression-4.1.6.RELEASE.jar
    • spring-instrument-4.1.6.RELEASE.jar
    • spring-jdbc-4.1.6.RELEASE.jar
    • spring-orm-4.1.6.RELEASE.jar
    • spring-tx-4.1.6.RELEASE.jar
    • spring-web-4.1.6.RELEASE.jar
    • spring-webmvc-4.1.6.RELEASE.jar
  • slf4j (Logging)

    • slf4j-api-1.7.12.jar
    • slf4j-simple-1.7.12.jar (just for the example)
    • jcl-over-slf4j-1.7.12.jar
      Additionally, I setup my application to use PARENT_LAST classloading. This is just something I have gotten used to, so if you have difficulties getting your code to work and you are not in PARENT_LAST, give that a try.

Setting up web.xml

First, add the following for Spring:

    <context-param>
       <param-name>contextConfigLocation</param-name>
       <param-value>/WEB-INF/spring/application-context.xml</param-value>
    </context-param>

    <listener>
       <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    <listener>
       <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
    </listener>

    <servlet>
       <servlet-name>dispatcher</servlet-name>
       <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
          <param-name>contextConfigLocation</param-name>
          <param-value>/WEB-INF/spring/servlet-context.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
       <servlet-name>dispatcher</servlet-name>
       <url-pattern>/</url-pattern>
    </servlet-mapping>
Next, I have my datasource bound to jdbc/ExampleDb, and my Persistence Unit name will be Example Unit, so I added:
    <resource-ref>
       <res-ref-name>jdbc/ExampleDb</res-ref-name>
       <res-type>javax.sql.DataSource</res-type>
       <res-auth>Container</res-auth>
       <res-sharing-scope>Shareable</res-sharing-scope>
    </resource-ref>

    <persistence-unit-ref>
       <persistence-unit-ref-name>persistence/ExampleUnit</persistence-unit-ref-name>
       <persistence-unit-name>ExampleUnit</persistence-unit-name>
    </persistence-unit-ref>

ibm-web-bnd.xml

Don’t forget to bind your data source resource in ibm-web-bnd.xml:

<resource-ref name="jdbc/ExampleDb" binding-name="jdbc/ExampleDb" />

Spring Configuration

The servlet-context.xml has nothing special in it for this example, but the application-context.xml does. It points Spring to the WebSphere UOW Transaction Manager, and references the persistence unit to use:

    <bean id="entityManagerFactory" class="javax.persistence.Persistence" factory-method="createEntityManagerFactory">
        <constructor-arg type="java.lang.String" value="ExampleUnit" />
    </bean>

    <bean id="transactionManager"
        class="org.springframework.transaction.jta.WebSphereUowTransactionManager" />
    <tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true" />

persistence.xml

And lastly, the persistence.xml:

<?xml version=”1.0” encoding=”UTF-8”?>
<persistence xmlns=”http://java.sun.com/xml/ns/persistence
xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance
xsi:schemaLocation=”http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd
version=”2.0”>
<persistence-unit name=”ExampleUnit” transaction-type=”JTA”>
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<jta-data-source>java:comp/env/jdbc/ExampleDb</jta-data-source>
<properties>
<property name=”hibernate.dialect” value=”org.hibernate.dialect.PostgreSQLDialect” />
<property name=”hibernate.transaction.factory_class” value=”org.hibernate.transaction.CMTTransactionFactory” />
<property name=”hibernate.transaction.jta.platform” value=”org.hibernate.service.jta.platform.internal.WebSphereExtendedJtaPlatform” />
<property name=”hibernate.transaction.flush_before_completion” value=”true” />
<property name=”hibernate.transaction.auto_close_session” value=”true” />
<property name=”hibernate.temp.use_jdbc_metadata_defaults” value=”false” />
<property name=”hibernate.show_sql” value=”false” />
<property name=”hibernate.query.substitutions” value=”true ‘Y’, false ‘N’” />
<property name=”hibernate.cache.use_second_level_cache” value=”true” />
</properties>
</persistence-unit>
</persistence>

Here we are doing the following:

  • Setting transaction-type to JTA (Java Transaction API)
  • Setting the JPA Provider to Hibernate
  • Setting the data source to our web component’s ExampleDb
  • Setting Hibernate to use the PostgreSQL dialect
  • Setting Hibernate to use the CMTTransactionFactory for container managed transactions
  • Setting Hibernate to use Webphere’s JTA Platform
  • And so on
    Note that I did have an issue with Hibernate on startup trying to determine type information, which is what hibernate.temp.use_jdbc_metadata_defaults resolved for me. I did not have to set this when using Oracle. This did not used to occur with older versions of Hibernate (e.g. 4.1.9.Final).

Congratulations!

WebSphere is now running a Spring MVC web application, leveraging JPA 2.0 and Hibernate! For my full source, checkout GitHub at https://github.com/craigstjean/WebSphere-JPA-Spring-Hibernate

WebSphere 7.0 Users

I have had success using Hibernate 4.1.9.Final using the same configuration, though I was using version 1.0 in my persistence.xml. Also, you must place the Hibernate JPA API 2.0 JAR that is included with Hibernate in the lib directory. If you migrate to WebSphere 8.5, you must remove that JAR.

Comment and share

Craig St. Jean

Father, programmer, constant learner, @pluralsight author


Software Architect