Mocking final classes with Mockito and JavaAssist

Sometime you need to mock final classes. I never got why people will write final classes, but since they do – and we need to mock those classes – here is a nice solution. I’m using JavaAssist here, which is a framework that can manipulate classes at run time.

Note that this code must run before anything else in your unit tests – Constructor, @Before, @BeforeClass, @PostConstruct (if you use Spring) annotations will not do. This has to be a static block on your unit test class (or its base). Otherwise, your final class will already be loaded, and you’ll get weird exceptions like “attempted duplicate class” LinkageError.
First of all – add JavaAssist to your project. I use gradle, so:

testCompile group: 'org.javassist', name: 'javassist', version: '3.22.0-GA'

Note the testCompile – we only use Mockito and JavaAssist on our test classes, so no need to bundle it in your code.
Then, write a static block on your unit test class (or it’s base class. Will work either way)

static {
try {
ClassPool cp = ClassPool.getDefault();
CtClass cc = cp.get("fully qualified class name");
cc.defrost();
int clzModifiers = cc.getModifiers();
clzModifiers = javassist.Modifier.clear(clzModifiers, Modifier.FINAL);
cc.setModifiers(clzModifiers);
cc.toClass();
} catch (Exception e) {
e.printStackTrace();
}
}

And walla. You can now use @MockBean, Mockito.mock or any other method you use to mock classes.
Enjoy.

Using BouncyCastle FIPS for Java FIPS support

How do you use BC FIPS in Java app?

I’ve been trying recently to use BC FIPS module in my Java app. Turns out – not as simple as you’d think.
The problems I faced were mainly with the keystore format, but other issues came up as well.

1. Download the bc-fips-1.0.0.jar (download latest and greatest from here) file
2. Place it in jre/lib/ext
3. Edit jre/lib/security/java.security file. Edit the following line:
security.provider.4=com.sun.net.ssl.internal.ssl.Provider BCFIPS
4. Edit jre/lib/security/java.security file. Add the following line:
security.provider.11=org.bouncycastle.jcajce.provider.BouncyCastleFipsProvider
(Make sure you use the right numbering. It should be consecutive)
5. Create your keystore:
keytool -genkey -storetype BCFKS -alias mykey -keyalg RSA -provider org.bouncycastle.jcajce.provider.BouncyCastleFipsProvider -storepass test123 -keystore test_fips
Of course, you can change the parameters are you need
6. Add the following line in your code (I prefer that over the java.security changes)
new com.sun.net.ssl.internal.ssl.Provider("BCFIPS");
7. If your code requires specifying the keystore type, use the following constant – BCFKS

You should be OK…

Implementing IGNORE_ROW_ON_DUPKEY_INDEX in Postgres

Unfortunately for us all, Postgres does not support the IGNORE_ROW_ON_DUPKEY_INDEX hint. So if you have highly concurrent code that inserts data to a table with a unique constraint, you’re in for allot of potential problems.

There is no easy fix (beside handling that scenario in the code). But if the insert rate to the table is not high, the following solution can work for you:

CREATE OR REPLACE FUNCTION lock_table() RETURNS trigger AS $$
DECLARE
  cnt integer;
  p_table_name varchar;
  p_query varchar;
  p_query_temp varchar;
  p_param_name varchar;
  p_param_type varchar;
BEGIN
  p_param_type = TG_ARGV[0];
  p_param_name = TG_ARGV[1];
  p_table_name = TG_TABLE_NAME || '_lock';

  EXECUTE 'SELECT $1."' || p_param_name || '"'
      USING NEW
       INTO p_query_temp;

  IF p_param_type = 'string' THEN
    p_query = 'select 1 from ' || TG_TABLE_NAME || ' where ' || p_param_name || '=''' || p_query_temp || '''';
  ELSE
    p_query = 'select 1 from ' || TG_TABLE_NAME || ' where ' || p_param_name || '=' || p_query_temp;
  END IF;

  execute 'lock table ' || p_table_name || '  in exclusive mode';
  execute p_query into cnt;
	IF cnt = 1 THEN
	  RETURN NULL;
	else
    RETURN NEW;
	END IF;

END; $$ LANGUAGE plpgsql;
/

create table my_table_lock(id varchar2(1024) not null);
/

CREATE TRIGGER my_table_on_duplicate_ignore BEFORE INSERT OR UPDATE ON parameter_name
    FOR EACH ROW EXECUTE procedure lock_table('string','name');
/

Now, locking table for exclusive mode forces the database to write rows one by one, and disable concurrency. It’s not perfect – but it will work.

Another word of caution – this solution might break your ORM tool (specifically – it happened for me on Hibernate), as returning NULL from the trigger causes the update count to be decreased to 0. Couldn’t find a good way around that problem. If you have an idea – I’d be happy to hear it.

Inject beans into JBoss 7 Modules

It seems like JBoss 7.0 CDI has an issue with injecting beans that are located in shared libraries, and are not part of an EAR file. Irritating (but solved in the next version). However, I didn’t want to upgrade, so I decided to solve it instead.
Here’s a short step-by-step:

Deltaspike

Deltaspike is an apache library that has several useful CDI extensions. Add it as a module to your jboss-as. You can use the following module.xml file:

<?xml version="1.0" encoding="UTF-8"?>
 
<module xmlns="urn:jboss:module:1.1" name="org.deltaspike">
 
    <resources>
        <resource-root path="deltaspike-core-api.jar" />
        <resource-root path="deltaspike-core-impl.jar" />
    </resources>
 
    <dependencies>
        <module name="com.google.guava" />
        <module name="javax.enterprise.api" />
        <module name="javax.inject.api" />
    </dependencies>
</module>

Reflections

Reflections is a very useful library that allows you to find classes that has an annotation in runtime.
Add it as a module to your jboss-as.

<?xml version="1.0" encoding="UTF-8"?>
 
<module xmlns="urn:jboss:module:1.1" name="org.reflections">
 
    <resources>
        <resource-root path="reflections.jar" />
    </resources>
 
    <dependencies>
        <module name="com.google.guava" />
        <module name="org.javassist" />
        <module name="org.slf4j" />
    </dependencies>
</module>

Module extensions

This is the heart of the solution. This module runs when the CDI container starts, and adds relevant beans to the CDI. Make sure this class is part of a JAR file that is inside your EAR file!

This code is greatly influenced from https://rmannibucau.wordpress.com/2013/08/19/adding-legacy-beans-to-cdi-context-a-cdi-extension-sample/

package com.tona.cdi;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import javax.enterprise.event.Observes;
import javax.enterprise.inject.Any;
import javax.enterprise.inject.spi.AfterBeanDiscovery;
import javax.enterprise.inject.spi.AnnotatedType;
import javax.enterprise.inject.spi.Bean;
import javax.enterprise.inject.spi.BeanManager;
import javax.enterprise.inject.spi.BeforeBeanDiscovery;
import javax.enterprise.inject.spi.Extension;
import javax.enterprise.util.AnnotationLiteral;
import javax.inject.Named;
import javax.inject.Singleton;

import org.apache.deltaspike.core.util.bean.BeanBuilder;
import org.apache.deltaspike.core.util.metadata.builder.AnnotatedTypeBuilder;
import org.reflections.Reflections;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.base.Strings;

public class ModuleConfigurationExtension implements Extension {
    private static final Logger log = LoggerFactory.getLogger(ModuleConfigurationExtension.class);
    private final Map beans = new HashMap();

    /**
     * This method is automatically activated by CDI, and loads all classes in the com.tona package that has NAMED or
     * SINGLETON annotations.
     * @param bdd
     */
    void readAllConfigurations(final @Observes BeforeBeanDiscovery bdd, BeanManager bm) {
        log.info("Starting to load beans from modules");
        addBeansFromPackage(bdd, bm, "com.tona");
    }

    private void addBeansFromPackage(final BeforeBeanDiscovery bdd, BeanManager bm, String packageName) {
        Reflections reflections = new Reflections(packageName);
        Set beanClasses = reflections.getTypesAnnotatedWith(Named.class);
        beanClasses.addAll(reflections.getTypesAnnotatedWith(Singleton.class));

        for (Class bean : beanClasses) {
            @SuppressWarnings({ "unchecked", "rawtypes" })
            AnnotatedType annotatedType = new AnnotatedTypeBuilder().readFromType(bean).create();
            Set foundBeans = bm.getBeans(annotatedType.getBaseType(), new AnnotationLiteral() {
            });

            if (foundBeans.size() == 0) {
                bdd.addAnnotatedType(annotatedType);
                String name;
                Named named = bean.getAnnotation(Named.class);
                if (named == null || Strings.isNullOrEmpty(named.value())) {
                    name = bean.getSimpleName();
                } else {
                    name = named.value();
                }
                beans.put(name, annotatedType);
            }
        }
    }

    /**
     * This method actually initializes the beans we discovered in <code>readAllConfigurations</code>. Again - this
     * method is automatically activated by CDI
     * @param abd
     * @param bm
     * @throws Exception
     */
    public void addCdiBeans(final @Observes AfterBeanDiscovery abd, final BeanManager bm) throws Exception {
        log.info("Starting to initialize beans from modules");

        for (Map.Entry bean : beans.entrySet()) {
            Set foundBeans = bm.getBeans(bean.getValue().getBaseType(), new AnnotationLiteral() {
            });

            if (foundBeans.size() == 0) {
                final Bean cdiBean = createBean(bm, bean.getKey(), bean.getValue());
                abd.addBean(cdiBean);
                log.debug("Added bean " + cdiBean.getName());
            }
        }
    }

    private static Bean createBean(final BeanManager bm,
            final String name,
            final AnnotatedType annotatedType)
            throws Exception {
        final BeanBuilder beanBuilder = new BeanBuilder(bm).
                readFromType(annotatedType).
                name(name);

        return beanBuilder.create();
    }
}

Configuring the extension

Create a file called META-INF/services/javax.enterprise.inject.spi.Extension. It should only have the following line:

com.tona.cdi.ModuleConfigurationExtension

Updating your EAR file

The EAR file should have dependencies on the org.deltaspike and org.reflections module. Add it in the MANIFEST.MF file.

Salesforce Delegated Authentication

This post is radically different from my previous posts – it’s going to be written in C#!!!
Salesforce allows users to use a delegated authentication mechanism for SSO. One option is SAML, which is nice – but it doesn’t work on mobile devices in disconnected mode. The other is delegated authentication. This way, Salesforce activates a web service that implements a predefined WSDL. The parameters the web service is getting are the username, password and IP address, and the service needs to return a true/false value.
So, let’s get down to business:

  1. Configure Delegated Authentication
    1. Open your Salesforce account for delegated authentication. For some reason, this is not enabled by default, and you need to ask your SF guys to enable this features.
    2. Login to Salesforce, and click the Setup link
    3. Click Security Controls→Single Sign-On Settings
    4. Click on Edit, and enter your Web Service URL
  2. Assign users to the Delegated Authentication
    1. Login to Salesforce, and click the Setup link
    2. Click Manage Users→Profiles
    3. Select the user profile
    4. Click the Edit button
    5. Make sure the “Is Single Sign-On Enabled” checkbox is enabled
    6. Click Save

    And now the code

    using System;
    using System.Collections.Generic;
    using System.Configuration;
    using System.DirectoryServices;
    using System.DirectoryServices.Protocols;
    using System.IO;
    using System.Linq;
    using System.Net;
    using System.Security.Cryptography.X509Certificates;
    using System.Threading;
    using System.Web;
    using System.Web.Services;
    
    namespace DelegatedAuthenticationService
    {
        /// <summary>
        /// This service is used for delegated security for force.com
        /// </summary>
        [WebService(Namespace = "urn:authentication.soap.sforce.com", Description="v1.1.3")]
        [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
        [System.ComponentModel.ToolboxItem(false)]
        public class DelegatedSecurityService : System.Web.Services.WebService, IAuthenticationBinding
        {
            [WebMethod]
            public bool Authenticate(string username, string password, string sourceIp, System.Xml.XmlElement[] Any)
            {
                    try
                    {
                        // Run the business logic
    	                return true;
                    }
                    catch (Exception e)
                    {
                        // Connection can not be created - password is incorrect
                        log(ERROR,"Failed to get LDAP connection. Error message is : " + e.Message);
                        audit(username, "FAIL",e.Message);
                        return false;
                    }
            }
        }
    }
    

    It’s important to note that Salesforce is limiting the time it will waits for the service – the entire request/response (including network) must take less than ~5 seconds, otherwise users will get a failed to login message.

    Good luck!

jmap, jstack not working properly with OpenJDK

I run into an issue lately with the jmap and jstack implementation of OpenJDK. Quite frankly – they didn’t work…
When running jmap -heap, I would get:

Exception in thread "main" java.lang.reflect.InvocationTargetException
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:606)
	at sun.tools.jmap.JMap.runTool(JMap.java:197)
	at sun.tools.jmap.JMap.main(JMap.java:128)
Caused by: java.lang.RuntimeException: unknown CollectedHeap type : class sun.jvm.hotspot.gc_interface.CollectedHeap
	at sun.jvm.hotspot.tools.HeapSummary.run(HeapSummary.java:146)
	at sun.jvm.hotspot.tools.Tool.start(Tool.java:221)
	at sun.jvm.hotspot.tools.HeapSummary.main(HeapSummary.java:40)
	... 6 more

When running jstack -F I would get:

java.lang.RuntimeException: Unable to deduce type of thread from address 0x00007fc980001000 (expected type JavaThread, CompilerThread, ServiceThread, JvmtiAgentThread, or SurrogateLockerThread)
	at sun.jvm.hotspot.runtime.Threads.createJavaThreadWrapper(Threads.java:162)
	at sun.jvm.hotspot.runtime.Threads.first(Threads.java:150)
	at sun.jvm.hotspot.runtime.DeadlockDetector.createThreadTable(DeadlockDetector.java:149)
	at sun.jvm.hotspot.runtime.DeadlockDetector.print(DeadlockDetector.java:56)
	at sun.jvm.hotspot.runtime.DeadlockDetector.print(DeadlockDetector.java:39)
	at sun.jvm.hotspot.tools.StackTrace.run(StackTrace.java:52)
	at sun.jvm.hotspot.tools.StackTrace.run(StackTrace.java:45)
	at sun.jvm.hotspot.tools.JStack.run(JStack.java:60)
	at sun.jvm.hotspot.tools.Tool.start(Tool.java:221)
	at sun.jvm.hotspot.tools.JStack.main(JStack.java:86)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:606)
	at sun.tools.jstack.JStack.runJStackTool(JStack.java:136)
	at sun.tools.jstack.JStack.main(JStack.java:102)
Caused by: sun.jvm.hotspot.types.WrongTypeException: No suitable match for type of address 0x00007fc980001000
	at sun.jvm.hotspot.runtime.InstanceConstructor.newWrongTypeException(InstanceConstructor.java:62)
	at sun.jvm.hotspot.runtime.VirtualConstructor.instantiateWrapperFor(VirtualConstructor.java:80)
	at sun.jvm.hotspot.runtime.Threads.createJavaThreadWrapper(Threads.java:158)
	... 15 more
Can't print deadlocks:Unable to deduce type of thread from address 0x00007fc980001000 (expected type JavaThread, CompilerThread, ServiceThread, JvmtiAgentThread, or SurrogateLockerThread)

The fix was simple (as some dear guys in the OpenJDK explained to me). Make sure you install openjdk-debuginfo package. That should fix it.

Using Oracle’s ListAgg with distinct

Oracle’s 11g ListAgg function is a great way to concat multiple rows into a single column. However, it has a major limitation (in addition to the light documentation) – you can’t use distinct in ListAgg, a serious limitation. Online solutions suggest subqueries or regular expressions. I decided to write my own aggregate function to replace ListAgg.
Here goes:

  • First of all, I created the type specification:
    create or replace type TextAggregation as object
    (
      aggString VARCHAR2(32767), 
      static function ODCIAggregateInitialize(sctx IN OUT TextAggregation) 
        return number,
      member function ODCIAggregateIterate(self IN OUT TextAggregation, 
        value IN VARCHAR2) return number,
      member function ODCIAggregateTerminate(self IN TextAggregation, 
        returnValue OUT VARCHAR2, flags IN VARCHAR2) return number,
      member function ODCIAggregateMerge(self IN OUT TextAggregation, 
        ctx2 IN TextAggregation) return number
    );
    /
    
  • Then, the type body:
    create or replace type body TextAggregation is 
    static function ODCIAggregateInitialize(sctx IN OUT TextAggregation) 
    return number is 
    begin
      sctx := TextAggregation('');
      return ODCIConst.Success;
    end;
    
    member function ODCIAggregateIterate(self IN OUT TextAggregation, value IN VARCHAR2) return number is
      location number;
    begin
    	location := instr(',' || aggString || ',' , ',' || value || ',');
    	
    	if location > 0 then
    		return ODCIConst.Success;
    	end if;
    	
      if (aggString is null) then
        aggString := value;
      else
        aggString := aggString || ',' || value;
      end if;
      
    	return ODCIConst.Success;
    end;
    
    member function ODCIAggregateTerminate(self IN TextAggregation, 
        returnValue OUT VARCHAR2, flags IN VARCHAR2) return number is
    begin
      returnValue := self.aggString;
      return ODCIConst.Success;
    end;
    
    member function ODCIAggregateMerge(self IN OUT TextAggregation, ctx2 IN TextAggregation) return number is
    begin
      self.aggString := ctx2.aggString;
      return ODCIConst.Success;
    end;
    end;
    /
    
  • And then the actual function
    CREATE or replace FUNCTION MyListAgg (input VARCHAR2) RETURN VARCHAR2 PARALLEL_ENABLE AGGREGATE USING TextAggregation;
    /