Use Hamcrest Matchers in JMockIt

JMockIt, when used together with Hamcrest matchers, can sometimes create very flexible verifications in unit test. This is demonstrated in the gist here.

The test class GameConrollerTest defines a test target (with @Tested) and a mocked object (in this case it is a class only with static methods, with @Mocked). In the only test method testCreatPerson(), it sets up an expectation, followed by invoking the target method under test, then finally provides a verification block to assert that some behaviors from the mocked object(class) have been invoked. The verification code snippet is provided below

    new Verifications() {
      {
        PersonFactory.createFighter(withArgThat(
            Matchers.allOf(Matchers.<Person>hasProperty("name", Matchers.equalTo(name1)),
                Matchers.hasProperty("age", Matchers.equalTo(age1)))));
        times = 1;
        PersonFactory.createFighter(withArgThat(
            Matchers.allOf(Matchers.<Person>hasProperty("name", Matchers.equalTo(name2)),
                Matchers.hasProperty("age", Matchers.equalTo(age2)))));
        times = 1;
      }
    };

The withArgThat() method can take any of the Hamcrest matcher of type <? super T> and returns an object of type T. This is where the magics happen because you can create a matcher that matches anything you need. In addition to the many convenient factory methods provided by Hamcrest Matchers util class, you can always provide your own matchers by implementing the Matcherinterface or extending any of its implementing classes. Here you can find a few good tutorials. Also you can refer to this one.

Posted in Java | Tagged , , , , | Leave a comment

Spring Bean Configure XML Accessing Context.xml JNDI Resources

Tomcat context.xml can expose environment variables accessible by Spring bean configuration xml files.

Problem:

Sometimes you want to externalize some application properties, such as password or QA/Production specific settings, used by Spring beans. There are a few options for doing so and this post focuses mainly on Tomcat based web application by putting the properties in its context.xml file.

Solution:

Step#1: Put the properties into context.xml as environment entities

<Context>
  <Environment name="myPassword" value="xxx" type="java.lang.String" override="false"/>
</Context>

This essentially exposes the properties to JNDI java.comp/env context.

Step#2: Access them from Spring bean config file

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:lang="http://www.springframework.org/schema/lang"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/lang
http://www.springframework.org/schema/lang/spring-lang-3.0.xsd">  
<bean id="myPasswordBean" class="org.springframework.jndi.JndiObjectFactoryBean">
	<property name="jndiName" value="java:comp/env/myPassword"/>
</bean>
</beans>

Now you get a reference of myPassword defined in the context.xml.

Other Solutions:
There are a few other ways to externalize the bean properties without Tomcat, such as passing them in from JVM arguments or in a separated properties files using PropertyPlaceholderConfigurer. They are not covered by this post.

Posted in Java | Tagged , , , , , , | Leave a comment

Use SpringBoot to Deploy ActiveMQ Broker to Tomcat-2/3

This post is to continue the first part of the same topic. It mainly covers:

  1. Use commercial database as the data store
  2. Use the embedded Tomcat to manage the data source connection pool

Background

Despite the fact that the ActiveMQ buildin Kaha database is more efficient when handling messages, we sometimes need to take other consideration too. For example, if your production environment prefers to database based backup and disaster recovery than NAS, you have to consider database.

Use MS-SQL-Server as the data store

There are many ways to create a datasource for ActiveMQ. This post creates one with SpringBoot and pass it to Tomcat for pool management.

Step#1: Add dependency spring-boot-starter-jdbc into the build file, and then add the following section into the application.properties file

spring.datasource.driver-class-name=com.microsoft.sqlserver.jdbc.SQLServerDriver
spring.datasource.url=jdbc:sqlserver://localhost:1433;databaseName=jms
spring.datasource.username=user
spring.datasource.password=password

Step#2: Disable broker auto-start. You need to ensure the broker is started after the data source is injected. This is done by calling

BrokerFactory.setStartDefault(false);

in the SpringBoot main() method, and then explicitly start it after setting the persistent adapter for the broker:

broker.setPersistenceAdapter(jdbcPersistenceAdapter);
broker.start();

Use Tomcat to manage the connection pool

This can be easily done by adding the following into application.properties file

#Tomcat connection pool
spring.datasource.tomcat.max-active=10
spring.datasource.tomcat.test-on-borrow=true
spring.datasource.tomcat.validation_query=SELECT 1
spring.datasource.tomcat.log_abandonded=true
spring.datasource.tomcat.remove_abandonded=true
spring.datasource.tomcat.remove_abandonded_timeout=60

Source Code

The source code can be viewed or downloaded from here.

Special Notes

You may see build error due to missing mssql jdbc driver. You need to specify your repository that hosts the driver artifact, or put it into your local gradle cache.

You can find the next related post here.

Posted in Java | Tagged , , , , | 1 Comment

Use SpringBoot to Deploy ActiveMQ Broker to Tomcat 1/3

This topic has three parts. Also See part2 in next post and part3.

ActiveMQ can be installed as a standalone server, or it can run within other containers, such as Spring or web containers. When deploying in Tomcat, you have the options of deploying a war file to a standalone Tomcat or using the embedded container provided by SpringBoot.

VM Based Broker in SpringBoot

If a VM based broker is good enough for you (when prototyping or integration testing), you can easily get it up running in minutes. Please see the ActiveMQ SpringBoot example as your start point.

Fully Configurable Broker

If you need a broker with full controllability, you can follow this post here. This post uses Gradle for build. Please see the source code in GitHub. Or you can download the commit by clicking here.

  1. Dependency.  In this example, we selectively choose a few basic individual activemq artifacts instead of using the SpringBoot ActiveMQ starter. Note that there is a activemq-all artifact available, but you may end up in logback conflict with SpringBoot. Since activemq-all artifact is generated by Maven shade plugin, it is hard to exclude logback from activemq-all. So this post uses individual jars. If you need to support other functionalities, please reference to activemq-all pom file.
  2. ActiveMQ configuration is provided by activemq.xml. Here you have all the flexibility to configure your broker. Alternative to the XML based configuration, you can in fact create a BrokerService bean and configure it programmatically in Java.
  3. The ActiveMQ broker is managed by Spring context defined in my-beans.xml, which is exposed to the SpringBoot by annotation @ImportResource(“classpath:my-beans.xml”) in the ActiveMqApplication.java class.
  4. application.properties provides variables that you can change value without changing code. You can also pass in different values when you start your program.

Build and Run

Assume you already have gradle installed, then

  1. git clone https://github.com/liuzy163/activemq-server.git
  2. change your working directory into activemq-server
  3. gradle build
  4. find the executable jar file from activemq-server/build/libs/activemq-server-1.0.jar
  5. java -Dserver.port=9988 -jar activemq-server-1.0.jar

Now you have a running activemq broker listening tcp port 61616.

Posted in Java | Tagged , , , , | 2 Comments

Use JIRA as Your Workflow Engine

The main advantage of JIRA, by comparing to the most of other Java Workflow engines, is that it is an issue centric system. It does not only provide workflow management for issues, but also provides other issue oriented functionalities such as reporting, searching, tracking, authorizing, assigning and timing etc. A thorough discussion can not be covered by blogs. Here I plan use a few blogs to highlight (or provide some links) a few things when customizing JIRA as part of your software application.

JIRA Product

JIRA has three different flavours, JIRA  Core, JIRA Software and JIRA Service Desk. At the time of writing, JIRA Core is not a standalone product and it is used as the foundation of the latter two products. JIRA Software pre-bundles software development plugins such as the agile, scrum and bug tracking functionalities. JIRA Service Desk pre-bundles some IT or support desk related functionalities. One big sale point of the JIRA Service Desk is that it integrates a customer portal, which can be used for expose some controllable and customizable information to your customers.

You can try any edition of JIRA for one month for free. Or you can pay $10 for a perpetual license.

If your product requires high scalability and reliability, you can consider the clustered data center version, which  of course costs much more.

Install and Run

JIRA can be downloaded from Atlanssian website. You can  run its installer to install it. Some of the key concepts during installation are:

  • JIRA installation directory, where you install JIRA application to
  • JIRA_HOME, where you store JIRA configuration (such as how to connect to DB, logs, scripts, attachment, and avatar etc.)
  • Install as service vs standalone: Install as service gives you better log output
  • DB: it uses the embedded H2 by default. You can overwrite it at the end of the installation. You can also change the database after installation but it requires more steps.
  • It also requires you to set up an admin account. Remember your password. Otherwise you need to reset it with a few steps involving SQL.

Once installed, you can log into your JIRA by http://localhost:portNumber.  Once logged in, you’d better to change the base url to http://yourHostName:port if you want other people to access it (Settings->System->Base URL).

Useful Plugins

You can find many useful third party plugins for your development or business purpose. You can go to Atlanssian Marketplace to find them. From your JIRA, you can go to Settings->Add-ons->Find new add-ons.

Two useful plugins I have tried are ScriptRunner for JIRA and Configuration Manager. Both vendors provides good web materials and excellent customer support. The ScriptRunner provided many build-in script for you to customize your fields and workflow. And it also provide the capability to provide more complicated Groovy script. The latter one let you easily manage most of your configuration, for example, generating system level or project level configuration snapshot and deploy the snapshot to different JIRA server instances. More on those two plugins later.

If you can not find any plugin fit in your specific needs, you can always write your plugin to access many JIRA resources. More on this topic later.

Develop your JIRA Data Model (Later)

  • JIRA data model
  • System configuration
  • Project configuration
  • Webhooks

Talk to your JIRA (Later)

  • Web UI
  • SDK
  • REST APIs
  • Plugins

Version Control Your Code (Later)

Deploy Your Release (Later)

Posted in JIRA | Tagged | Leave a comment

Parse X509Certificate to JSON

Parsing a X509Certificate file into JSON object in string using groovy is demonstrated here.

import groovy.json.JsonOutput
import groovy.json.JsonSlurper

import java.security.cert.CertificateFactory
import java.security.cert.X509Certificate

class CertificateParser {

  public static def parseFileToJson(def path) {
    return toJason(parseX509Certificate(new File(path).newInputStream()))
  }

  private static def toJason(X509Certificate certificate){
    def builder = new groovy.json.JsonBuilder()
    def timeZone = TimeZone.getTimeZone("America/New_York")
    builder{
      expiryDate certificate.getNotAfter().format("yyyy-MM-dd hh:mm:ss", timeZone)
      subjectDN certificate.getSubjectDN()
      subjectAlternativeNames CertificateParserHelper.getSubjectAltName(certificate)
      eku CertificateParserHelper.getExtendedKeyUsageAsText(certificate)
      issuerDN certificate.getIssuerDN()
      issuerUniqueID certificate.getIssuerUniqueID()
      issuerAlternativeNames certificate.getIssuerAlternativeNames()
      issuerX500Principal certificate.getIssuerX500Principal()
      subjectUniqueID certificate.getSubjectUniqueID()
      subjectX500Principal certificate.getSubjectX500Principal()
      serialNumber certificate.getSerialNumber()
      sigAlgName certificate.getSigAlgName()
      sigAlgOID certificate.getSigAlgOID()
      signature certificate.getSignature()
      type certificate.getType()
      version certificate.getVersion()
    }
    return JsonOutput.prettyPrint(builder.toString())
  }

  private static def parseX509Certificate(def inputStream){
    def CertificateFactory cf = CertificateFactory.getInstance("X.509");
    return inputStream.withStream { s->
      (X509Certificate)cf.generateCertificate(s)
    }
  }
}

The helper class can be found below as

import java.security.cert.X509Certificate
class CertificateParserHelper {
  private static final EXTENDED_KEY_USAGE_OID_STRINGS = [
    "2.5.29.37.0",
    "1.3.6.1.5.5.7.3.0",
    "1.3.6.1.5.5.7.3.1",
    "1.3.6.1.5.5.7.3.2",
    "1.3.6.1.5.5.7.3.3",
    "1.3.6.1.5.5.7.3.4",
    "1.3.6.1.5.5.7.3.5",
    "1.3.6.1.5.5.7.3.6",
    "1.3.6.1.5.5.7.3.7",
    "1.3.6.1.5.5.7.3.8",
    "1.3.6.1.4.1.311.20.2.2",
    "1.3.6.1.5.5.7.3.9"
  ];

  private static final EXTENDED_KEY_USAGE_TEXTS = [
    "All Usages",
    "All Usages",
    "Server Authentication",
    "Client Authentication",
    "Code Signing",
    "Email Protection",
    "IPSec end system",
    "IPSec tunnel",
    "IPSec user",
    "Timestamping",
    "Smartcard Logon",
    "OCSP signer"
  ];


  public static List<String> getExtendedKeyUsageAsText(X509Certificate certificate) {
    def extendedKeyUsageOidToTextMap = [EXTENDED_KEY_USAGE_OID_STRINGS, EXTENDED_KEY_USAGE_TEXTS].transpose().collectEntries{it}
    try {
      def extendedkeyusage = certificate.getExtendedKeyUsage();
      if (extendedkeyusage == null){
        return [];
      }
      def returnval = []
      extendedkeyusage.each{it->
        returnval.push(extendedKeyUsageOidToTextMap.get(it));
      }
      return returnval;
    } catch (java.security.cert.CertificateParsingException e) {
      //log.error("certificate parsing exception" + e.getLocalizedMessage(), e);
      throw e;
    }
  }

  public static getSubjectAltName(X509Certificate certificate) {
    def result=[]
    def sans = certificate.getSubjectAlternativeNames()
    try {
      if ( sans!= null) {
        sans.each {iter->
          String name = (String)iter.get(1);
          if (name != null){
            result.push(name);
          }
        }
      }
    } catch (java.security.cert.CertificateParsingException e) {
      result = e.getMessage();
    }

    return result;
  }
}

Posted in Groovy | Tagged , , | Leave a comment

Cleanup Stale Hibernate Session in Tomcat

Problem:
When Hibernate is configured to use thread based session management, a thread may get stuck (unable to unbind) with a closed session under certain condition, therefore all subsequent incoming HTTP calls assigned to such a thread would fail until Tomcat is restarted. At problem time, you may see exceptions like “org.hibernate.exception.GenericJDBCException: Cannot release connection.”

Cause:
The typical pseudo code (either standalone or inserted into servlet filter) that can suffer this problem is

Session session = getSessionFactory().getCurrentSession();
try{
  session.getTransaction().commit();
}catch(Throwable t){
  session.getTransaction().rollback();
}finally{
  if(session.isOpen()){
    session.close();
  }
}

When the commit succeeded, Hibernate will unbind the session from the thread and close the session. However if there is an exception occurred during commit, Hibernate may not able to unbind before it closes the session. The related Hibernate pseudo code (see ConnectionManager, JDBCContext, JDBCTransaction, SessionImpl and TreadLocalSessionContext for detail) is

try{
     commitTransaction();
     unbindSessionFromThread()
}finally{
     closeSession()
}

Solution:
Manually unbind the session from the thread is doable but not recommended. In Tomcat, you can use its DBCP or JDBC connection pool configuration to remove stale sessions therefore obtain new sessions on next HTTP call. The full document can be found here, and a sample configure using context.xml is followed below:

&lt;Resource name="jdbc/myDb" auth="Container" type="javax.sql.DataSource"
      maxActive="100" maxIdle="30" maxWait="10000"
      validationQuery="SELECT 1"
      username="xxxxxx" password="xxxxxxx"
      driverClassName="com.microsoft.sqlserver.jdbc.SQLServerDriver"
      url="jdbc:sqlserver://127.0.0.1:1433;DatabaseName=myDb"
      factory="org.apache.tomcat.jdbc.pool.DataSourceFactory"
      logAbandoned="true"
      removeAbandoned="true"
      removeAbandonedTimeout="600"
      testOnBorrow="true"
	  /&gt;

You may need to copy your jdbc driver jar (i.e. sqljdbc4-4.0.2206.100.jar) into the tomcat lib directory before starting it as the JDBC driver and the DataSourceFactory need to be loaded by the same class loader.

Posted in Database, Java | Tagged , , , , | Leave a comment