Sunday, November 3, 2019

Generating SHA-256 checksums for Maven artifacts

This one is thoroughly undocumented. Didn't go through the plugins code to work this one out, it worked purely by chance...

My organization requires that for all artifacts to be released, a SHA-25 checksum needs to be generated. I've standardized on pom.xml for all projects in order to upload artifacts to Nexus. My alternative was to upload artifacts via Jenkins in a pipeline using the Nexus uploader block, however it doesn't seem there's a simple way to get identify ahead of time the artifacts that would be built in the Maven dependency tree. If there was, I could just run "sha256sum" on this list... I did try suggestion from here but if I recall it didn't list artifacts from child modules: https://stackoverflow.com/questions/36936238/create-a-list-of-artifacts-that-are-build-by-a-maven-project

Far easier to use a Maven plugin with "mvn deploy". Cue the checksum-maven-plugin:
https://checksum-maven-plugin.nicoulaj.net/examples/generating-project-artifacts-checksums.html

Looks simple enough. Quote: "This configuration will generate checksum digest files for the project main and attached artifacts".

      <plugin>
        <groupId>net.nicoulaj.maven.plugins</groupId>
        <artifactId>checksum-maven-plugin</artifactId>
        <version>1.8</version>
        <executions>
          <execution>
            <goals>
              <goal>artifacts</goal>
            </goals>
          </execution>
        </executions>
        <configuration>
          <!-- put your configurations here -->
        </configuration>
      </plugin>
When I tried this plugin, no SHA-256 checksum gets generated.

Within the responses on the Github repository for that plugin, I find this:
https://github.com/nicoulaj/checksum-maven-plugin/issues/39


<plugin>
    <groupId>net.ju-n.maven.plugins</groupId>
    <artifactId>checksum-maven-plugin</artifactId>
    <version>1.3</version>
    <executions>                   
        <execution>
            <id>checksum-artifacts</id>
            <phase>package</phase>
            <goals>
                <goal>artifacts</goal>
            </goals>
            <configuration>
                <csvSummary>false</csvSummary>
                <shasumSummary>true</shasumSummary>
                <shasumSummaryFile>sha512-libs.sum/shasumSummaryFile>
                <individualFiles>false</individualFiles>
                <algorithms>
                    <algorithm>SHA-512</algorithm>
                </algorithms>
                <types>
                    <type>jar</type>
                </types>
                <scopes>
                    <scope>runtime</scope>
                </scopes>
            </configuration>
        </execution>
    </executions>
</plugin>
I guess it used to have a different group name prior to version 1.5, however this version of the plugin was at least printing a line in the Maven output indicating this plugin was getting invoked. I thought my plugin wasn't even getting called! However still no checksum was getting generated.

I'd almost given up, until my colleague started using the plugin and SHA-256s were getting generated and auto-uploaded to Nexus. After a bit of digging, I found that only artifacts in the "${workspace}/target" directory were getting checksums generated. My artifacts were getting generated in child module folders, and any arbitrary directory the project called for - e.g. from using maven exec plugin or antrun.

The solution was to add an extra antrun step to move any built artifact into the project root's target directory, and then use attach-artifacts to include it for upload to Nexus. In some of my cases, I had to add an extra module to perform this after other child module's had completed building. Sometimes the Maven reactor wouldn't order the child module's properly, especially if the module's were built with proprietary Maven plugins (e.g. Temenos products). Not the user-friendly experience I expected for generating checksums!

Wednesday, February 22, 2017

MySQL driver and Fuse

The internet caused me a headache this past week.
All the guides on using MySQL with Fuse in a project utilizing Blueprint DSL will demonstrate something like this:
1. In your POM declare <Import-Package>com.mysql.jdbc</Import-Package>
2. Install mysql-connector to your OSGi container using "osgi:install"
3. Install your app.

Here's some links: Fuse examples on Git, http://stackoverflow.com/questions/30307288/mysql-connector-in-osgi-environment-gradle-noclassdeffounderror, http://freemanfang.blogspot.sg/2012/03/how-to-use-jdbc-driver-in-osgi.html, http://www.liquid-reality.de/display/liquid/2012/01/13/Apache+Karaf+Tutorial+Part+6+-+Database+Access

If you were getting error "java.lang.ClassNotFoundException: com.mysql.jdbc.Driver not found", you would probably come across the above guides. However, you would be severely misled, because they all do not address the fundamental issue: MySQL changed their package name of the Driver.class.
I guess this is one of the downfalls of proprietary libraries, they change package names at will, and there are 0 OSGi articles that mention this. So the easy fix to your solution would be:
1. Change this in your POM:

      <plugin>
        <groupId>org.apache.felix</groupId>
        <artifactId>maven-bundle-plugin</artifactId>
        <version>${version.maven-bundle-plugin}</version>
        <extensions>true</extensions>
        <configuration>
          <instructions>
             <Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
             <Bundle-Description>${project.description}</Bundle-Description>
             <Import-Package>com.mysql.cj.jdbc, com.ibm.mq.jms, com.ibm.mq, com.ibm.mq.constants ,org.springframework.jdbc.*, org.apache.commons.dbcp,*;resolution:=optional</Import-Package>
             <DynamicImport-Package>*</DynamicImport-Package>
          </instructions>
        </configuration>
      </plugin>


2. Change this in your blueprint:

    <bean class="org.apache.commons.dbcp.BasicDataSource" id="dataSource">
        <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://localhost:3306/yourdb"/>
        <property name="username" value="user"/>
        <property name="password" value="pass"/>
    </bean>



I really hope this saves some people a heap of time!!

Tuesday, January 17, 2017

SoapUI and MQ on Windows

WebSphere MQ is a fairly complex piece of software, with concepts ranging from Connection Factories, Topics, Subscribers, Channels, etc. So getting SoapUI to connect to it requires a decent amount of technical know-how.
There's ample SoapUI documentation on picking up & sending messages to ActiveMQ, however for IBM MQ it's a bit sparse. This is an attempt to document, step by step, how to get SoapUI to quickly hook up to MQ, in Windows 7, taking into consideration UAC.
  1. Get WebSphere MQ Developer edition, if you don't have it already. I made the mistake of getting the evaluation trial.
  2. If working locally, create a queue manager in MQ, then open up command prompt, run "runmqsc ", and type "ALTER QMGR CHLAUTH(DISABLED)". You don't need to worry about channel authentication for development work, but if you insist, it took me some time to figure this out but you need to first create a server-connection channel (you had the option to do this on installation of MQ), open channel properties and under MCA, replace *NOACCESS with MUSR_MQADMIN (if using default domain/users).
  3. Go to %SOAPUI_HOME%/bin, open up "soapui.bat", and edit this line so it becomes:
    set CLASSPATH=%SOAPUI_HOME%soapui-5.3.0.jar;%SOAPUI_HOME%..\lib\*;C:\Program Files\IBM\WebSphere MQ\java\lib\*
    Then run this bat file as Administrator.
  4. Load up a WSDL in SoapUI. To save yourself some time, use the sample SoapUI SOAP tutorial which comes with the SoapUI installation. On Windows this is put in C:/Users/username/SoapUI-Tutorials by default.
  5. Run HermesJMS from within SoapUI. Configure the path to HermesJMS when it prompts you.
  6. Create a new session. This guide can take you through *most* of the way: Guide
    But you might get numerous errors about classes not being runnable. In my classpath group I ended up with this, just to be sure.
  7. If you left channel authentication on, you need to connect through the server-connection channel. Your session configuration needs to look like this:

    (And yes that's a Mac UI, Mac users can follow these instructions)
  8. Be careful not to leave "MQQueueConnectionFactory" as the Connection Factory for the session if you're getting classpath errors, otherwise your session will become corrupt and you'll need to delete the HermesJMS hermes-config.xml file and start over.
  9. Right click session, Discover, and HermesJMS should find all your queues.

Sunday, December 18, 2016

Finding the Eclipse test client URL

Generate a bottom-up web service and deploy to Eclipse Tomcat, and the internal browser automatically pops up:


Now, what if you close that browser? Well you're in a predicament, you either have to:
- regenerate the test client project
- guess the URL of the sample test project

This caused me much grief, so for reference, here's the URL:
http://localhost:/Client/sampleProxy/TestClient.jsp
Where your port is either the Tomcat port or the monitor port.

Friday, July 8, 2016

Oracle Linux & yum

Recently my wife had brought back a laptop with an Oracle Linux VM running on VMWare Fusion. It was based off RHEL 4.4 which I thought was pretty darned old. She was undergoing training at her new job and the class were trying to install the "screen" command with yum. Apparently not even the trainer could figure out how to get "yum" to work.

The first thing I noticed was the Red Hat subscription message:
This system is not registered to Red Hat Subscription Management. You can use subscription-manager to register.
Setting up Install Process
No package screen available.

I'd never setup an RHEL OS before, so I looked for online repos to add to yum.repos.d, and tried to enable the "rhel-source" repo that was available by default, but no dice.

After a bit of playing around, I realized I had to activate Red Hat subscription. I was quite surprised the company would give out VMs with expired/no subscriptions to freshies, for training! Instructions here: https://access.redhat.com/solutions/253273

First you have to create an account on the Red Hat portal. You can choose "Personal" or "Corporate", this confused me for awhile because you can't get an Evaluation Subscription without a corporate email address. This was restrictive based on the email address you provided (I gave a gmail account), but then changed it to her company's provided one. Then you have to activate the subscription, otherwise you'll get: <user> cannot register with any organizations. Once you have a subscription, you'll be able to run "yum install screen" (or any package for that matter!)

Hope this helps someone!

Sunday, June 19, 2016

Java 7 and SSL

We faced this at work a few days ago.
We run a Java standalone application, with embedded JBoss. It runs on Java 7. One of our customers insisted on TLSv1.2 protocol for their server.
Now, the issue with this is Java 8 has TLSv1.2 enabled by default. Java 7 doesn't, it's only got SSLv2 and 3 enabled by default.
Typically, just setting something like "-Ddeployment.security.TLSv1.2=true" to run your application would be sufficient, however our coders actually hardcoded the SSL context so this never worked...

Monday, April 18, 2016

Docker Machine on Windows

After having so much fun with running Docker in a Virtualbox VM, I decided to explore Docker's solution to running Docker on Windows. Turns out, there's really not much different, apart from using 'docker-machine create' to link Windows Docker commands to the VM one.

I run the Docker Quickstart terminal, which creates a 'default' VM under IP 192.168.99.100, with Docker installed and daemon running on port 2376. It has a NAT Network Adapter, with a randomly forwarded port (e.g. 56858) to guest port 22. It also creates a Host-Only Network Adapter in Virtualbox, named "Virtualbox Host-Only Ethernet Adapter", and this has a DHCP server enabled to distribute IPs. The adapter has an IP address of "192.168.99.1". The rest looks like this:



I had to figure all this out myself, and I really wish all this information was just laid out from the start on the Docker documentation.

My goal was to create a Virtualbox VM, and hook up Windows Docker commands to it. This gives me the flexibility of starting a VM via Vagrant, and not having to use boot2docker OS. Seems logical to me.

First, this line is required in Vagrantfile:
config.vm.network "private_network", type: "dhcp"


This will create a Host-Only network for you, meaning the VM will have an IP assigned by Virtualbox's DHCP server. I don't know about you, but I get an automatically assigned IP: 172.28.128.1

Then you need to somehow automatically determine this IP. You can use this:
"vagrant ssh -c "ip address show eth1 | grep 'inet ' | sed -e 's/^.inet //' -e 's/^([0-9.]+)./\1/'"

Note how I assume 'eth1'. This is because I expect to only have 2 adapters, and eth0 is used by the NAT adapter.

Knowing the IP of your VM, you can run this on Windows (you must pass in the private key to generic-ssh-key):
docker-machine -D create --driver generic --generic-ssh-user root --generic-ssh-key myfolder/id_rsa --generic-ip-address 172.28.128.4 --generic-ssh-port 22 myserver


But then you may encounter this:
Error running SSH command: exit status 127

This actually requires you to put your public key into the 'authorized_keys' file for that user (in my case, root) on your VM.

After that, you may get this:
Reading server key from C:\Users\Alkaiser\.docker\machine\machhefserver\server-key.pem
Error creating machine: Error checking the host: Error checkinor regenerating the certs: There was an error validating certis for host "172.28.128.4:2376": dial tcp 172.28.128.4:2376: i/out
You can attempt to regenerate them using 'docker-machine regencerts [name]'.
Be advised that this will trigger a Docker daemon restart whic stop running containers.


Other users suggest you have a conflicting Host-Only adapter. I wouldn't rule this out, however it is more likely your TCP connection is being blocked. You can validate this by running "telnet 172.28.128.4 2376". This should connect because the Docker daemon is listening on that port. If this doesn't work, it means your VM is blocking that port. On CentOS7, I unblock it by using:
firewall-cmd --permanent --zone=public --add-port=2376/tcp; systemctl restart firewalld


Now you should get (with debug output):
Docker is up and running!
Reticulating splines...
(chefserver) Calling .GetConfigRaw
To see how to connect your Docker Client to the Docker Engine g on this virtual machine, run: D:\Program Files\Docker Toolboer-machine.exe env chefserver
Making call to close driver server
(chefserver) Calling .Close
Successfully made call to close driver server
Making call to close connection to plugin binary
Making call to close driver server
(flag-lookup) Calling .Close
Successfully made call to close driver server
Making call to close connection to plugin binary


Have fun with your custom Docker machine!