2016. november 7., hétfő

Code templates for Eclipse

In my daily work, I found very productive to use my own code templates for Eclipse. By the time, I have collected a useful set of templates.

You can define your own templates by opening the dialog under Preferences\Java\Editor\Templates

Defining templates is quite straightforward. If you need a detailed introduction, please refer to the following source in Tutorialspoint.

Tips and tricks


Make it accessible

As it is possible to export and import templates, I keep my templates file under version control, so I can use them easily in all of my projects.

Naming

Naming my own templates is important, while I need to select them all for export, I want to handle them together, and I want to find them during the coding really fast.
Therefore I add the prefix "my" to the template name, and use namespaces to group my templates. So, my templates are named like this:

  • my.junit.assertTrue
  • my.log.createLogger
  • my.stringUtils.notBlank


Variables

You can use variables in your template, which makes it possible to define complex expressions.
You can found a complete list of the variables found here

Imports

If you use any class in the template, that needs to be imported, define the required import statements as well. Sometime I generate a template for commonly used classes, just for spare the time of importing the needed package. Commons StringUtils is such an example for it. 


${:import(org.slf4j.Logger,org.slf4j.LoggerFactory)}
// Logger instance
private static final Logger log = LoggerFactory.getLogger(${enclosing_type}.class);${cursor}


Static imports

If you use methods, to be imported statically, you can use the staicImport keyword


${is:importStatic('org.junit.Assert.assertTrue')}

assertTrue(${cursor});


My Templates are stored under GitHub, and free to use by anyone. It contains following templates:
  • Singleton
  • Lazy initialization in getter method
  • Basic JUnit assertions with imports
  • AssertThat method calls with static exports
  • Mockito commands (when, mock, times)
  • JUnit exception testing with the @Rule annotation
  • Logging (create logger, using different log methods, logging for exception)
  • Input validation for methods, using commons validation
  • generating enumeration with a field inside 
  • Fixme and Todo templates




2016. november 4., péntek

Using reflection in setup phase of unit testing

It is  a common practice to use mock framework in the setup phase of a unit test, in order to set the internal state of the dependent objects. Sometimes it is though easier to set a value of a given field directly, in order to test the class accordingly.

For modifying field value via reflection, I used the reflection utility classes from the org.apache.commons.lang3.reflect package.

In my example I had a class, responsible to holding the application configuration, which is loaded from an XML file. The default location of the configuration file is hard-coded into the class. I wanted however test the loadConfig method, with different test configuration files, in order to check all possible configuration cases.


public class ConfigurationHolder {

    private static final String DEFAULT_CONFIGURATION_FILE_LOCATION = "./src/main/conf/cleaner.xml";

    private final String configurationFileLocation;

    private CleanerConfiguration cleanerConfiguration;

    private final static ConfigurationHolder instance = new ConfigurationHolder();

    private ConfigurationHolder() {
        this.configurationFileLocation = DEFAULT_CONFIGURATION_FILE_LOCATION;
    }

    public CleanerConfiguration getConfiguration() {
        if (cleanerConfiguration == null) {
            loadConfig();
        }

        return cleanerConfiguration;
    }

    private void loadConfig() {
        try {
            JAXBContext jaxbContext = JAXBContext.newInstance(CleanerConfiguration.class);
            Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
            File file = new File(configurationFileLocation);
            cleanerConfiguration = (CleanerConfiguration) jaxbUnmarshaller.unmarshal(file);
        } catch (JAXBException e) {
            throw new RuntimeException("Problem with cleaner configuration: " + e.getMessage());
        }
    }

    public static ConfigurationHolder getInstance() {
        return instance;
    }

}

With using mock framework I would have had design following possibilities:
  • creating a class, like ConfigurationFileLocationProvider or ConfigurationFileProvider to deliver the location of the file, or the file itself, and use the class in ConfigurationHolder.
    In this case I believe, I would have introduced a dependency just to make testing possible.
     
  • Passing the file location in the constructor. In this case I would have lost the possibility to use the class as singleton. 

So I decide to keep the simple implementation, and use reflection for the unit test. I decided to use the commons reflections package, while it seams to be a more sophisticated solution as the one from Spring framework.

As I wanted to set the value of a simple private field, I implemented the following method in the unit test class:


private ConfigurationHolder createConfigurationHolder(String configFileLocation) throws IllegalAccessException {
    ConfigurationHolder cr = ConfigurationHolder.getInstance();
    FieldUtils.writeField(cr, "configurationFileLocation", configFileLocation, true);
    FieldUtils.writeField(cr, "cleanerConfiguration", null, true);
    return cr;
}

In my test case I use this method to create a new instance, with the given file location

@Test
public void testGetConfiguration() throws Exception {
    String configFileLocation = "./src/test/conf/cleaner-config-test.xml";
    ConfigurationHolder cr = createConfigurationHolder(configFileLocation);

    CleanerConfiguration configuration = cr.getConfiguration();
    Assert.assertThat(configuration, notNullValue());
}


As always, you need to consider what brings you to modify the state for unit test, and which possible problems can you face with.

Advantages.
  • you can change the internal state of your class without adding unwanted dependencies to it.
  • you can test objects without setter methods like classes used for XML or JSON data modelling (with @XmlRootElement or @JsonAutoDetect annotation). These classes are generated usually without setter methods, and instances get filled up via reflection.  

Disadvantages
  • as in case of the solution, where unit testing is done via mock framework, you need to design the class carefully, to avoid restrictions regarding reflection. In this case, I had to use the configurationFileLocation property, while, the DEFAULT_CONFIGURATION_FILE_LOCATION constant can not be modified by reflection.
  • As name of the field to be modified via reflection is hard-coded into the unit test case, you need to be careful when refactoring the class. I do not see it as a big risk, however, while you need to run unit test during the refactoring anyway, so you will be forced the change the relevant test cases as well.  

Further useful methods from the FieldUtils class:
  • removeFinalModifier() makes it possible to change even final fields
  • writeStaticField() makes it possible to change even static fields



2016. szeptember 28., szerda

Using Application Link in Atlassian plugins



When implementing complex plug-ins for the Atlassian suite, it might be needed to request information from another Atlassian application. You can see examples for it, when JIRA shows Stash commits, of Confluence pages.

As all Atlassian applications has a REST API, it is possible to make JSON calls directly. Using Application Links for communication between Atlassian products however has following advantages

  • It uses central authentication of the Atlassian applications. You can take advantage of the centralized CROWD user management, and don't need to store user and password in some configuration of your plug-in. You also don't need to set authentication data in your code.
  • You use components of the common com.atlassian.applinks.api package, and it is part of the core features of all Atlassian applications. All needed components are included in com.atlassian.applinks maven group, which is automatically included by the application. Therefore you do not need to add any additional maven dependencies to your project.
  • As application liking is supported by all Atlassian products, you can reach all of them with a single programming API from your add-on.
Disadvantage of the solution is, that you are working with pure JSON responses, so in order to map them into the Java world, you need a mapping framework (like Jackson or Gson), and most probably implement your own classes holding the returned information.

If you want to use a single application, with a more object oriented way, you can consider using product specific API.s like JiraRestClient from the com.atlassian.jira.rest.client.api package.  

Configuring Application link

In order to use functionalities of JIRA from my Confluence plug-in, I have created an Application link between the two servers. In local development environment I had to configure the link to use the "Trusted application" authentication type, in order to get it worked.

I made the following steps to create the application link

  1. Start the JIRA and the Confluence server locally, using the atlassian-run command in the root directory of the plug-ins.
  2. Log in as admin to both applications
  3. In JIRA navigate to Administration/Applications/Application links
  4. Create a new application link following the wizard. The process includes to go to the Confluence administration page and set the inverse link as well.
  5. After the application links are visible on both of the servers, set the authentication for incoming and outgoing link to "OAuth (impersonation)" everywhere.
    Doing so, you configures trusted application connection, and you do not need to bother with authentication in the plug-in code.

Implementing usage of Application link

I have implemented an example to show, how to get a list of all JIRA fields in Confluence using the application link to JIRA.

The call via application link uses the REST API URL providing field information: http://javadeveloper:2990/jira/rest/api/2/field

The result from JIRA looks like this:


[
{"id":"issuetype","name":"Issue Type","custom":false,"orderable":true,
 "navigable":true,"searchable":true,"clauseNames":["issuetype","type"],
 "schema":{"type":"issuetype","system":"issuetype"}},
{"id":"components","name":"Component/s","custom":false,"orderable":true,
  "navigable":true,"searchable":true,"clauseNames":["component"],
  "schema":{"type":"array","items":"component","system":"components"}}, ...

At the first step, I create an ApplicationLinkRequest pointing to the given URL. 


final static int APP_LINK_TIME_OUT = 60000;

// Logger instance
private static final Logger log = LoggerFactory.getLogger(JiraServiceCaller.class);

@Autowired
private ApplicationLinkService appLinkService;

/**
 * Creates ApplicationLinkRequest for calling JIRA REST service, based on the restServiceUrl parameter.
 * 
 * @param restServiceUrl
 * @return
 */
protected ApplicationLinkRequest createApplicationLinkRequest(String restServiceUrl) {
 MethodType methodType = Request.MethodType.POST;
 ApplicationLinkRequest aplrq = createApplicationLinkRequest(restServiceUrl, methodType);
 return aplrq;
}

private ApplicationLinkRequest createApplicationLinkRequest(String restServiceUrl, MethodType methodType) {
 ApplicationLink appLink = appLinkService.getPrimaryApplicationLink(JiraApplicationType.class);
 if (appLink == null) {
  log.info("Failed to handle REST request. CredentialsRequiredException occured.");
  throw new JiraConnectionException("Unable to get application link of type 'JiraApplication'");
 }

 ApplicationLinkRequestFactory factory = appLink.createAuthenticatedRequestFactory();
  ApplicationLinkRequest aplrq = null;
 try {
  aplrq = factory.createRequest(methodType, appLink.getRpcUrl() + restServiceUrl);
  aplrq.setSoTimeout(APP_LINK_TIME_OUT);

 } catch (CredentialsRequiredException e) {
  log.warn("Error while creating ApplicationLinkRequest", e);
  throw new JiraConnectionException("Unable to connect JIRA via application link. Error message: '" + e.getMessage() + "'");
 }
 return aplrq;
}


Than I execute the configured ApplicationLinkRequest to get the result of the REST API call.


private static final String REST_JIRA_RETRIEVE_FIELDS = "/rest/api/2/field";
 
/**
 * Retrieves a list containing name of all existing JIRA fields
 */
@Override
public List<String> retrieveFieldNames() {
 List<String> result = new ArrayList<String>();

 try {
  ApplicationLinkRequest alr = createApplicationLinkGetRequest(REST_JIRA_RETRIEVE_FIELDS);
  String jiraResponse = alr.execute();
  if (StringUtils.isNotBlank(jiraResponse)) {
   ObjectMapper mapper = new ObjectMapper();
   JsonJiraField[] myObjects = mapper.readValue(jiraResponse, JsonJiraField[].class);
   for (int i = 0; i < myObjects.length; i++) {
    JsonJiraField jsonJiraField = myObjects[i];
    result.add(jsonJiraField.getName());
   }
  }
 } catch (IOException | ResponseException e) {
  log.warn("Failed to handle REST request. IOException occured.", e.getMessage());
 }
 return result;
}


For mapping between the JSON sting and the Java code, I implemented a simple value object, holding the JIRA field info, and used the ObjectMapper from Jackson to fill it up with data.     

Add parameters to the REST call

The ApplicationLinkRequest makes it possible to add parameters to your REST call as key - value pairs, like this:



alr.addRequestParameters("projectKey", projectKey);






2016. szeptember 27., kedd

Different ways to use assertions in Java code



In order to create a clean and save code, I prefer implement as many state checks in my code, as possible or necessary.

If a state check fails, you usually want to throw an exception and stop processing the current business step. Failure in state check is always a sign of an implementation problem. As this kind of problems should be found in your test phase, your end user must not face with this kind of exceptions.

You should consider using assertion in the following situations:
  • Parameter check of the non private methods used by your own components.  
  • As it is stated in the many programming design guides, you always need to check parameters of a public method. It helps to provide a clean API and makes your code safer.
  • Check the state of your object before start to execute a critical operation.
It is also an advantage of assertions, that they can be considered as "active comments" in the code. Using assertions with appropriate error message documents the code, and has a well defined functionality at the same time. Assertions also help to test the API contract by writing Unit test direct against them.

You should carefully consider using assertions in following situations:
  • Checking parameters of private methods. In most cases unnecessary, as the caller of the method can be controlled by you.
  • Check returned objects from other software components, treating them as they would be an input to your component. As the connection and returned objects can be dependent of the environment, it does not necessary indicates a programming error if they are not in an appropriate state. In such situations throw a business exception instead. 

You have following ways to implement assertions

Simple Java check

Implementing the state check with a normal Java code, and throw the appropriate exception, when it fails.

Advantages
  1. You are not bound to a specific framework. 
  2. You can throw any kind of exception, depending of the situation. 
  3. You can implement your own Exception (preferably as a subclass of RuntimeEcxeption), and use it for validations. You can implement the appropriate exception handling for validation problems, make it possible for example to log them separately. You can even inform the developers about problems in production environment.

Disadvantages
  1. You are repeating yourself in the code. 
  2. In a team, all members will implement their own validation, with different, ad hoc Exceptions, and they will tend to forget adding meaningful messages to the exceptions.
  3. You do not have a common way to handle validation failures, as any kind of exception can be thrown. 
  4. Therefore you will soon start to implement your own little framework for validating the state, which is the root of the evil :) 

Java assertion



 public void setRefreshInterval(int interval) {
    // validate input parameter
    assert interval > 0 && interval <= 1000/MAX_REFRESH_RATE : interval;


Advantages
  1. The check is done only in test or development environment, which makes the production code slightly faster.
  2. AssertionError must not be cought, also it does not require additional code to handle it.
Disadvantages
  1. The check is done only in test or development environment, which makes problems, that not found during the acceptance very dangerous. Casing exceptions (if you are lucky) or incorrect business operations (if you are not so lucky)
  2. It is not always obvious to run unit tests with assertions enabled. However in case of Maven's Surefire plugin, assertions are swithced on by default, you need to check this when using other build tools.
    Starting Unit test with assertions enabled from a development tool, like Eclipse is also not convenient.  

Guava Preconditions class

Using the Preconditions class from Guava framework makes it easy to define simple validation rules. It has however not too much methods to be used.

Advantages
  1. Single utility class to validate conditions
Disadvantages
  1. A small set of validation methods

Commons Validate class

Using the Validate class makes it easy to implement validation rules. Its convenient methods are easy to use, and have a very easy to read naming convention.

Advantages
  1. Works with older Java versions as well.
  2. Lots of methods to check null values, collections, ranges, special checks for Strings.
  3. Continuously growing set of methods
Disadvantages
  1. Validation can not be restricted to test evironment
  2. There is no possibility to inform the developer, when problem occures in production.
Sources
http://www.cnblogs.com/rollenholt/p/3655511.html
http://stackoverflow.com/questions/5172948/should-we-always-check-each-parameter-of-method-in-java-for-null-in-the-first-li























2016. szeptember 21., szerda

Figure out if a field has been changed in JIRA event handler




At the previous post I have created an event handler for JIRA issues. Now, I will show how to check if a particular field has been changed during the event to be handled.

JIRA uses GenericValue objects from org.ofbiz.core.entity package to store event related information. GenericValue is basically a Map implementation to store all kind of data. So the key for finding the information we need is to know, which map keys we need to use to gain the data.

I have implemented a small utility class to find relevant elements in the issue event, and answer if a given field has been changed.


import java.util.List;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.ofbiz.core.entity.GenericEntityException;
import org.ofbiz.core.entity.GenericValue;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.atlassian.jira.event.issue.IssueEvent;
import com.atlassian.jira.issue.fields.CustomField;
import com.google.common.collect.ImmutableMap;

/**
 * Wrapper class to gain custom field specific information from the JIRA issue event
 * 
 * @author Peter Varga
 *
 */
class IssueEventWrapper {
 // keys to be searched in GenericValue objects
 private static final String KEY_CHANGE_ITEM = "ChangeItem";
 private static final String KEY_ID = "id";
 private static final String KEY_GROUP = "group";
 private static final String KEY_FIELD = "field";

 // Logger instance
 private static final Logger log = LoggerFactory.getLogger(IssueEventWrapper.class);

 private final IssueEvent issueEvent;

 /**
  * @param issueEvent
  */
 public IssueEventWrapper(IssueEvent issueEvent) {
  super();
  this.issueEvent = issueEvent;
 }

 /**
  * Answers if value of the given field has been changed during the issue event
  * 
  * @param customField
  * @return true if value of the given field has been changed
  */
 boolean fieldValueHasChanged(CustomField customField) {
  try {
   GenericValue changeLog = issueEvent.getChangeLog();
   if (changeLog == null) {
    return false;
   }

   List<GenericValue> changeItems = findChangeItems(changeLog);
   if (CollectionUtils.isEmpty(changeItems)) {
    return false;
   }

   for (GenericValue changedItem : changeItems) {
    // name of the field changed
    String field = changedItem.getString(KEY_FIELD);
    if (StringUtils.equals(field, customField.getFieldName())) {
     return true;
    }
   }
  } catch (GenericEntityException ex) {
   log.error(ex.getMessage(), ex);
  }
  return false;
 }

 /*
  * Returns list of change items, containing a single change information for each changed fields of the issue.
  */
 private List<GenericValue> findChangeItems(GenericValue changeLog) throws GenericEntityException {
  Object id = changeLog.get(KEY_ID);
  ImmutableMap<String, Object> map = new ImmutableMap.Builder<String, Object>().put(KEY_GROUP, id).build();
  return changeLog.internalDelegator.findByAnd(KEY_CHANGE_ITEM, map);
 }

}




Creating event listener for JIRA issue


Issue update event listener makes it possible to when the issue is created or modified in JIRA. As the event listener is registered to the lifecycle of the issue, the listener will be notified independently of the actual GUI element, used to create or update the issue.

Also the event listener will be notified after

  • new issue has been created 
  • issue has been modified via the edit issue popup
  • editing the issue directly on the display issue page
  • modifying the issue by sour application
  • modifying the issue via REST API
You need to implement the listener class. You don't need to implement any particular interface, but create following methods:
  • event handler method, marked with the @EventListener annotation.
  • method for registering the listener, marked with the @PostConstruct annotation.
  • method for unregistering the listener, marked with the @PreDestroy annotation.


package at.a1ta.eap.tasktrack.jira.ppm.fieldsync.eventlistener;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import com.atlassian.event.api.EventListener;
import com.atlassian.event.api.EventPublisher;
import com.atlassian.jira.event.issue.IssueEvent;
import com.atlassian.jira.event.type.EventType;
import com.atlassian.jira.issue.Issue;

/**
 * Issue update event listener. Makes it possible to handle event when the issue is created or modified in JIRA.
 * 
 * @author Peter Varga
 *
 */
public class IssueListener {
 // Logger instance
 private static final Logger log = LoggerFactory.getLogger(IssueListener.class);

 @Autowired
 private EventPublisher eventPublisher;

 @PostConstruct
 private void init() {
  eventPublisher.register(this);
  log.debug("at.a1ta.eap.tasktrack.jira.ppm.fieldsync.eventlistener.IssueListener registered to EventPublisher");
 }

 @PreDestroy
 private void preDestroy() {
  eventPublisher.unregister(this);
  log.debug("at.a1ta.eap.tasktrack.jira.ppm.fieldsync.eventlistener.IssueListener unregistered form EventPublisher");
 }

 @EventListener
 public void onIssueEvent(IssueEvent issueEvent) {
  Long eventTypeId = issueEvent.getEventTypeId();
  if (!isEventTypeToBehandled(eventTypeId)) {
   return;
  }

  Issue issue = issueEvent.getIssue();

  log.info("Issue changed {}", issue);

 }

 /**
  * Answers if the event type needs to be handled by this listener. IN this case when issue created or updated. For more event types, refer to the
  * {@link EventType} class.
  */
 private boolean isEventTypeToBehandled(Long eventTypeId) {
  return eventTypeId.equals(EventType.ISSUE_CREATED_ID) || eventTypeId.equals(EventType.ISSUE_UPDATED_ID);
 }

}


To register the event listener, you need to add the following entries into your atlassian-plugin.xml


<component-import key="eventPublisher" interface="com.atlassian.event.api.EventPublisher" />
<component key="eventListener" class="at.a1ta.eap.tasktrack.jira.ppm.fieldsync.eventlistener.IssueListener">
 <description>Class that processes the incoming JIRA issue events.</description>
</component>

Tips and tricks


  • Do not forget to unregister the listener. If you do, the event handling goes several time at the background, without noticing it, an causes performance problems.
  • The event listener will be fired for all issues on the system. Therefore, in order to avoid performance drops, you need to decide as soon as possible, if the event is relevant to you. I suggest filtering the events by it's type.   


2016. május 11., szerda

How to use @Rule annotation instead of the expected keyword to unit test exceptions


The usual way for unit testing expected exceptions looks like this:


@Test(expected = ConfigurationException.class)

It has although the following disadvantages:


  • you can not check details of the exception, like message or cause
  • you can not do anything with the exception

It is a better solution to use the @Rule annotation from JUnit.


import org.hamcrest.core.StringContains;
import org.junit.Assert;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;

@Rule
public ExpectedException exception = ExpectedException.none();

@Test
public void crowdUserDataThrowsExceptionForBlankInput() {
    exception.expect(IllegalArgumentException.class);
    exception.expectMessage("Username from CROWD must not be empty.");
    new CrowdDataImporter().new CrowdUserIdHolder("    ");
}

It is also possible to check the expected exception message, using some subclass of Matcher:

@Test
public void testCreateSchedulerCalendar_emptyParam() {
exception.expect(SchedulerException.class);
exception.expectMessage(new StringContains("job.scheduler.fixtime"));
avatarSyncJobScheduler.createSchedulerCalendar("");
}

You can find other Matcher implementations in the package org.hamcrest.core. It is per default added to the JUnit, so there is no need to add other maven dependencies is needed.