Using wsadmin to quickly restart IBM Connections (or WebSphere) applications

Restarting WebSphere applications using the wsadmin tool feels much faster than through the WebSphere Integrated Solutions Console.

If you’ve already invoked wsadmin to update a configuration then this is especially true. No navigating through menus to find the right item, just a “simple” command line and the application quickly restarts.

Here’s how…

Invoke wsadmin:

cd /opt/IBM/WebSphere/AppServer/profiles/Dmgr01/bin
./wsadmin.sh -lang jython -user icadmin -password PASSWORD_HERE

If you can’t remember the name of your applications, list the applications installed.

AdminApp.list()

This returns a somewhat unattractive string:

'Activities\nBlogs\nCommon\nCommunities\nConnectionsProxy\nDefaultApplication\nDogear\nEditLiveForConnections\nExtensions\nFileNetEngine\nFiles\nForums\nHelp\nHomepage\nMetrics\nMobile\nMobile Administration\nModeration\nNews\nProfiles\nPushNotification\nSearch\nWebSphereOauth20SP\nWidgetContainer\nWikis\nnavigator\noEmbed'

It’s better formatted:

Activities
Blogs
Common
Communities
ConnectionsProxy
DefaultApplication
Dogear
EditLiveForConnections
Extensions
FileNetEngine
Files
Forums
Help
Homepage
Metrics
Mobile
Mobile Administration
Moderation
News
Profiles
PushNotification
Search
WebSphereOauth20SP
WidgetContainer
Wikis
navigator
oEmbed

Aside
If you’ve recently changed any configurations, you may want to update the IBM Connections configuration and synchronise nodes at this point:

execfile("connectionsConfig.py")
LCConfigService.checkOutConfig("/tmp","connectionsCell01")
LCConfigService.updateConfig("versionStamp","")
LCConfigService.checkInConfig("/tmp","connectionsCell01")
synchAllNodes()

Choose one of the applications, for example Communities, then stop and start the application:

appManager=AdminControl.queryNames("cell=connectionsCell01,node=connectionsNode01,type=ApplicationManager,process=IC_server1,*")
AdminControl.invoke(appManager, "stopApplication", "Communities")
AdminControl.invoke(appManager, "startApplication", "Communities")

This is pretty quick. Often no more than 30 seconds.

Speeding up the Atlassian SDK with JRebel

jrebel-atlassian

JRebel saves compile time. It “Instantly reload changes to Java classes” – that’s the marketing talk anyway.

The theory is great. Anything has to be better than the randomness of Atlassian’s FastDev or atlas-cli, right? If it’s really worth the hype, I want to use it with the Atlassian SDK and speed up my development time. Here’s a short tutorial for JIRA development. Scroll down to the video if you want a demo.

Getting up and running…

Here’s my quick “how to” get up and running.
Get the jrebel.jar and save it somewhere – like /opt/jrebel/jrebel.jar

Add the jvmArgs in the plugin to point at said file (and turn off fast dev)…

<plugin>
     <groupId>com.atlassian.maven.plugins</groupId>
     <artifactId>maven-jira-plugin</artifactId>
     <version>${amps.version}</version>
     <extensions>true</extensions>
     <configuration>
          <productVersion>${jira.version}</productVersion>
          <productDataVersion>${jira.data.version}</productDataVersion>
          <enableFastdev>false</enableFastdev>
          <log4jProperties>src/main/extra/log4j.properties</log4jProperties>
          <jvmArgs>-javaagent:/opt/jrebel/jrebel.jar</jvmArgs>
     </configuration>
</plugin>

Add the jrebel-maven-plugin under build > plugins (see details of what does what here).

<plugin>
    <groupId>org.zeroturnaround</groupId>
    <artifactId>jrebel-maven-plugin</artifactId>
    <version>1.1.5</version>
    <configuration>
        <addResourcesDirToRebelXml>true</addResourcesDirToRebelXml>
        <alwaysGenerate>true</alwaysGenerate>
        <showGenerated>true</showGenerated>
    </configuration>
    <executions>
        <execution>
            <id>generate-rebel-xml</id>
            <phase>process-resources</phase>
            <goals>
                <goal>generate</goal>
            </goals>
        </execution>
    </executions>
</plugin>

Run atlas-run or atlas-debug on the command line, checking for any errors.

In Intelli-J, enable automatic compiling on code change by checking Make project build automatically:

make

Change something in your code & reload the page.

All is automatically updated. Immediately. No more waiting for code compile changes.

Check this quick video demo:

The good news – it’s pretty cool. The bad news – JRebel costs around $365 per seat per year. But think of all the time you save.

Runing a web server in the current directory

Sometimes I want to run a simple web server in the current directory.

There are many ways to do this. Here’s here’s one using npm / serve .

Installation

npm install serve -g
. ~/.profile

Running

cd /path/to/directory
serve

You get this message:

serving /path/to/directory on port 3000

You can now access the directory in a browser:

serve

Options

There are more options available:

serve -h

  Usage: serve [options] [dir]

  Options:

    -h, --help                output usage information
    -V, --version             output the version number
    -a, --auth <user>:<pass>  specify basic auth credentials
    -F, --format <fmt>        specify the log format string
    -p, --port <port>         specify the port [3000]
    -H, --hidden              enable hidden file serving
    -S, --no-stylus           disable stylus rendering
    -J, --no-jade             disable jade rendering
        --no-less             disable less css rendering
    -I, --no-icons            disable icons
    -L, --no-logs             disable request logging
    -D, --no-dirs             disable directory serving
    -f, --favicon <path>      serve the given favicon
    -C, --cors                allows cross origin access serving
        --compress            gzip or deflate the response
        --exec <cmd>          execute command on each request

Automated native2ascii character conversion for internationalisation of Atlassian add-ons

i18n-feature

Normally, I write my internationalisation (i18n) files in UTF-8 format. This means that they are human readable.

Java i18n files however must be ISO-8859-1. If you don’t process them using something like native2ascii, accented and multibyte characters will return gobbledegook at best.

You can manually convert a single file manually using this command:

native2ascii -encoding utf-8 ./src/main/resources/i18n.properties ./target/classes/i18n.properties

That’s tedious, so why not automate the process during the build?

Using native2ascii-maven-plugin

Luckily, there’s a maven plugin called native2ascii-maven-plugin. Its old, but does the job.

For Atlassian SDK p2 add-ons, use something like this:

<build>
    <plugins>
        <plugin>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>native2ascii-maven-plugin</artifactId>
            <version>1.0-alpha-1</version>
            <executions>
                <execution>
                    <id>native2ascii-utf8-properties</id>
                    <goals>
                        <goal>native2ascii</goal>
                    </goals>
                    <configuration>
                        <src>src/main/resources</src>
                        <includes>*.properties</includes>
                        <encoding>UTF8</encoding>
                        <dest>target/classes</dest>
                    </configuration>
                </execution>
            </executions>

            <!-- For Java 7+ compilation: -->
            <dependencies>
                <dependency>
                    <groupId>com.sun</groupId>
                    <artifactId>tools</artifactId>
                    <version>1.5.0</version>
                    <scope>system</scope>
                    <systemPath>${java.home}/../lib/tools.jar</systemPath>
                </dependency>
            </dependencies>
        </plugin>
		...
    </plugins>
</build>

Your source files will be in sweet UTF-8 format and your target files will be mangled into ISO-8859-1 as Java requires.

How do you do this? Please add a comment below with details.


Update: Maven resource filtering can mess with the working of this plugin, so try with no resource filtering first 😉

Releasing a locked port on a Mac / OS X

Sometimes a port doesn’t release properly resulting in servers staring on non-standard ports.

How do you release the port? Easy, use this:

lsof -i :portnumber

Grab the resulting PID and kill the process. Use -9 if you really have to.

Here’s a “worked example”:

$ lsof -i :1990
COMMAND  PID  USER   FD   TYPE             DEVICE SIZE/OFF NODE NAME
java    2857 david   39u  IPv6 0x23ed6292526f5971      0t0  TCP *:stun-p1 (LISTEN)
$ kill -9 2857

Customising Atlassian Confluence with header photos

header-image-demo-page

Header photos are all the rage (as my mother might say). Twitter has them. So does Facebook. Yup, even LinkedIn has them.

Confluence is a great platform for documentation, but what if you want to add extra some flare to your pages? Would a custom header photo be a good idea? Maybe so.

This post gives a simple method to do just that for pages that use the Default Theme.

In Confluence Admin | Configuration | User Macros create a new user macro:

## Macro: header-photo
## Author: David Simpson
##
## @param Photo:title=Header Photo|type=enum|enumValues=akabilk,captain_oblivion,rikpiks,renateflynn,grotan|default=red|desc=Choose a photo from one of these Flickr users
##
<script>AJS.toInit(function($){ $('body').addClass('header-photo photo-${paramPhoto}'); }); </script>

This gives you a user macro with some options to swap the background image between these images:

In Confluence Admin | Look and Feel | Stylesheet add the following:

/**  
 *  Uses the {header-photo} user macro to trigger the styles:
 */ 

.header-photo #main-header {
	margin: -20px;
	padding: 20px;
	background: #69c;
}

.header-photo #title-text {
	padding-top: 40px
}

.header-photo #breadcrumbs a,
.header-photo #title-text a,
.header-photo .page-metadata,
.header-photo .page-metadata ul li a
 {
	color: #fff;
	text-shadow: 2px 2px 5px #000;
}

/*** Hide these until mouseover/hover ***/
.header-photo #page-metadata-banner,
.header-photo #breadcrumbs,
.header-photo #navigation,
.header-photo .page-metadata {
	transition         : opacity .25s ease-in-out;
	-moz-transition    : opacity .25s ease-in-out;
	-webkit-transition : opacity .25s ease-in-out;
	opacity: 0;
}

/*** Display on mouseover/hover ***/
.header-photo #breadcrumbs:hover,
.header-photo #navigation:hover,
.header-photo .page-metadata:hover {
	opacity: 1;
}

.header-photo #main-header {
	background-size: cover;
	background-color: #000;
	background-position: 50% 50%;
}

/*** Each of these backgrounds has been selected from Flicker and uses a Creative Commons license ***/

/* From: flickr.com/photos/grotan/14035217861 */
.header-photo.photo-akabilk #main-header {
	background: #000 url(//davidsimpson.me/wp-content/uploads/2014/11/flickr.com-photos-grotan-14035217861.jpg)  no-repeat  ; 
}

/* From: flickr.com/photos/captain_oblivion/5601940290 */
.header-photo.photo-captain_oblivion #main-header {
	background-image:  url(//davidsimpson.me/wp-content/uploads/2014/11/flickr.com-photos-captain_oblivion-5601940290.jpg); 
}

/* From: flickr.com/photos/rikpiks/7721449224 */
.header-photo.photo-rikpiks #main-header {
	background-image: url(//davidsimpson.me/wp-content/uploads/2014/11/flickr.com-photos-rikpiks-7721449224.jpg); 
}

/* From: flickr.com/photos/renateflynn/8884401289 */
.header-photo.photo-renateflynn #main-header {
	background-image: url(//davidsimpson.me/wp-content/uploads/2014/11/flickr.com-photos-renateflynn-8884401289.jpg); 
}

/* From: flickr.com/photos/grotan/14035217861 */
.header-photo.photo-grotan #main-header {
	background-image: url(//davidsimpson.me/wp-content/uploads/2014/11/flickr.com-photos-grotan-14035217861.jpg); 
}

This is a simple bit of CSS that adds a different background to the page header based on the body class added in the user macro. I’ve purposefully chosen only dark backgrounds so that I can use a single text colour. Yes, that was quite lazy. You can embellish with more styles as required.

Here’s the macro configuration screen:

edit-header-photo-macro

The macro parameter values in the dropdown match the CSS classes in the custom global stylesheet. It’s pretty straightforward.

I’ve really restricted the number of photos available here. This is just an example of how you could implement a feature like this. You could easily adapt this for custom photos on every space or every page if you really feel like it.

Perhaps random photos is the way forward for you? If so, you could do worse than placekitten.com.

Secure development on Atlassian SDK using useHttps

Check the <useHttps>true</useHttps> configuration item. It appears to be a bit of a secret that could handle some more exposure. It starts Atlassian SDK running over HTTPS/SSL on port 443 without the need for a proxy server. Nice.

You can add it here:

<plugin>
    <groupId>com.atlassian.maven.plugins</groupId>
    <artifactId>maven-confluence-plugin</artifactId>
    <version>${amps.version}</version>
    <extensions>true</extensions>
    <configuration>
        <productVersion>${confluence.version}</productVersion>
        <productDataVersion>${confluence.data.version}</productDataVersion>
        <useHttps>true</useHttps>
     </configuration>
</plugin>

You’ll need to start the server like so:

sudo atlas-run

Otherwise, you’ll likely get the following error trying to bind to port 443 as a non-root user:

[INFO] [talledLocalContainer] SEVERE: Failed to initialize end point associated with ProtocolHandler ["http-bio-443"]
[INFO] [talledLocalContainer] java.net.BindException: Permission denied <null>:443
[INFO] [talledLocalContainer] 	at org.apache.tomcat.util.net.JIoEndpoint.bind(JIoEndpoint.java:406)
[INFO] [talledLocalContainer] 	at org.apache.tomcat.util.net.AbstractEndpoint.init(AbstractEndpoint.java:610)
[INFO] [talledLocalContainer] 	at org.apache.coyote.AbstractProtocol.init(AbstractProtocol.java:429)
[INFO] [talledLocalContainer] 	at org.apache.coyote.http11.AbstractHttp11JsseProtocol.init(AbstractHttp11JsseProtocol.java:119)
[INFO] [talledLocalContainer] 	at org.apache.catalina.connector.Connector.initInternal(Connector.java:981)
[INFO] [talledLocalContainer] 	at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:102)
[INFO] [talledLocalContainer] 	at org.apache.catalina.core.StandardService.initInternal(StandardService.java:559)
[INFO] [talledLocalContainer] 	at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:102)
[INFO] [talledLocalContainer] 	at org.apache.catalina.core.StandardServer.initInternal(StandardServer.java:814)
[INFO] [talledLocalContainer] 	at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:102)
[INFO] [talledLocalContainer] 	at org.apache.catalina.startup.Catalina.load(Catalina.java:633)
[INFO] [talledLocalContainer] 	at org.apache.catalina.startup.Catalina.load(Catalina.java:658)
[INFO] [talledLocalContainer] 	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
[INFO] [talledLocalContainer] 	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
[INFO] [talledLocalContainer] 	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
[INFO] [talledLocalContainer] 	at java.lang.reflect.Method.invoke(Method.java:606)
[INFO] [talledLocalContainer] 	at org.apache.catalina.startup.Bootstrap.load(Bootstrap.java:281)
[INFO] [talledLocalContainer] 	at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:455)
[INFO] [talledLocalContainer] Caused by: java.net.BindException: Permission denied
[INFO] [talledLocalContainer] 	at java.net.PlainSocketImpl.socketBind(Native Method)
[INFO] [talledLocalContainer] 	at java.net.AbstractPlainSocketImpl.bind(AbstractPlainSocketImpl.java:376)
[INFO] [talledLocalContainer] 	at java.net.ServerSocket.bind(ServerSocket.java:376)
[INFO] [talledLocalContainer] 	at java.net.ServerSocket.<init>(ServerSocket.java:237)
[INFO] [talledLocalContainer] 	at java.net.ServerSocket.<init>(ServerSocket.java:181)
[INFO] [talledLocalContainer] 	at javax.net.ssl.SSLServerSocket.<init>(SSLServerSocket.java:136)
[INFO] [talledLocalContainer] 	at sun.security.ssl.SSLServerSocketImpl.<init>(SSLServerSocketImpl.java:107)
[INFO] [talledLocalContainer] 	at sun.security.ssl.SSLServerSocketFactoryImpl.createServerSocket(SSLServerSocketFactoryImpl.java:84)
[INFO] [talledLocalContainer] 	at org.apache.tomcat.util.net.jsse.JSSESocketFactory.createSocket(JSSESocketFactory.java:182)
[INFO] [talledLocalContainer] 	at org.apache.tomcat.util.net.JIoEndpoint.bind(JIoEndpoint.java:393)
[INFO] [talledLocalContainer] 	... 17 more
[INFO] [talledLocalContainer] 

Does this work well?

Yes and no. It’s super easy to get going provided you remember about root permissions, but there are drawbacks.

You have to sudo on redeploys, and well, pretty much everything you do.

This seems like overkill though:

sudo atlas-package

atlas-install-plugin or sudo atlas-install-plugin doesn’t work as it tries to install to port 1990 for Confluence, 2990 for JIRA and so forth.

I ended up uploading the plugin via the UPM each time it was redeployed. That’s just rubbish.

This however, should work nicely:

sudo atlas-install-plugin --http-port 443

Will I continue to use this?

I’m not sure at the moment, unless its just for a very quick test or for JIRA development. Proxying with nginx is so easy. It’s setup and forget easy, at least for Confluence.

Debugging opensocial gadgets in IBM Connections

My standard IBM Connections installation has the following logging settings:

     *=info:
     com.ibm.social.pim.resource.*=all:
     com.ibm.lconn.homepage.services.widget.*=all:
     com.ibm.lconn.news.*=all:
     com.ibm.lconn.events.*=all:
     com.ibm.lotus.search.engine.*=all:
     com.ibm.lotus.search.index.*=all:
     com.ibm.lconn.mailin.*=all:
     com.ibm.lotus.connections.core.notify.*=all:
     com.ibm.lconn.scheduler.*=all:
     org.apache.shindig.*=all

In WebSphere, this is displayed on a single line:

*=info: com.ibm.social.pim.resource.*=all: com.ibm.lconn.homepage.services.widget.*=all: com.ibm.lconn.news.*=all: com.ibm.lconn.events.*=all: com.ibm.lotus.search.engine.*=all: com.ibm.lotus.search.index.*=all: com.ibm.lconn.mailin.*=all: com.ibm.lotus.connections.core.notify.*=all: com.ibm.lconn.scheduler.*=all: org.apache.shindig.*=all

Continue reading…

Atlassian Confluence hides create button and top navigation on license expiry

confluence-licensing

This was driving me crazy. I developed an add-on for Confluence, but sometimes the top navigation bar was missing items.

I was concerned that my add-on was really misbehaving and interfering in some way with the core product. There was no need to worry as Danielle figured it out.

On license expiry, rather than informing you that the license has expired, it simply disables features in the main header such as:

  • Spaces
  • People
  • Create button
  • The search box

If you run a product under the Atlassian SDK, you get a single day license. If you leave it overnight and come back, bits of the product (such as the Create button) get disabled. Restarting the product resets the license, so the disabled parts start working again. This doesn’t seem to be documented anywhere as far as I can tell.
Continue reading…