2017. november 21., kedd

Automatic dependency update detection with Gradle

Gradle has the possibility to check if the libraries used by your project has a new version. In order to use the feature, you need to add following elements to your Gradle configuration:


buildscript {
   dependencies {
        classpath 'com.github.ben-manes:gradle-versions-plugin:0.17.0'
    }
}
 
apply plugin: 'com.github.ben-manes.versions'

After configuring the project, you can start the following command to get the update info:

gradlew dependencyUpdates -Drevision=release

It lists the dependencies and possible newer versions.

What I learned 

  • Be careful, with the result of dependencyUpdates, while it is not hundred percent accurate.
  • It also can happen, that there are indirect dependencies between your libraries. In case of you need to get detailed information about the dependency hierarchy, you can use Gradle's dependency tree command.

    gradlew dependencies

    Unfortunately at the time of writing this post, there is no Eclipse support for the hierarchy tree.
  • Sometimes it is not even possible to use the latest version of a library. For example in case of Powermock, you need to check the compatibility page first
    https://github.com/powermock/powermock/wiki/Mockito
  • Due to indirect dependencies, it is not always possible to change to the latest version of a library directly. Simple defining the latest version can cause problems in Eclipse build or in the Gradle build process.

    In order to solve the problem, you need to exclude previous version of a given library used by another one. Excluding in Gradle looks like this:

    compile('org.springframework.boot:spring-boot-starter-test') {
        exclude group: 'org.mockito', module: 'mockito-core'
    }


2017. október 24., kedd

Implementing inheritance for JSON objects


Our App developers wanted to send slightly different JSON elements in a single list, in order to make the App side implementation far less complicated. In order to make it possible to, I decided to implement inheritance hierarchy for the JSON input and the related java DTO classes.

The other possibility would be to have a JSON object with union of the fields from all Java classes and using @JsonIgnoreProperties(ignoreUnknown = true) for them. In this way you would be able to parse only the relevant field into the given Java class.

Advantages of using hierarchy in JSON related classes:

  • more object oriented implementation
  • you can declare different type of objects in a single JSON list, so far they have the same Java super class
  • automatic REST input validation of the Spring framework still works for the classes. Yo do not need to define checking logic with mixed fields and complicated conditions. 
  • easy to add new types in the future, without effecting the existing ones 

Disadvantages:
  • you need to consider if storing different elements in a single list is a god idea at all
  • complicated structure
  • error prone type definition. It is not possible to define enumeration or any other typed value for the name property of @Type (see below)
  • unit testing of the hierarchy is more complicated
  • difficult to change break the hierarchy structure in case modification is needed later on

I created a common super class for the root of the inheritance and defined the field "actionType" for discriminator.  


@Data
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "actionType")
@JsonSubTypes({
 @Type(value = TriggeredNotificationActionDto.class, name = "NOTIFICATION"),
 @Type(value = TriggeredDeviceActionDto.class, name = "DEVICE")
})
public static class TriggeredActionDto implements Serializable {
 private String actionType;
}

I defined the actual sub-classes (using annotation of Lombok project for getter and setter generation). I also defined validators for the fields. They are used by the Spring framework when the objects are acting as input parameter of a REST call.

@Data
@EqualsAndHashCode(callSuper = true)
public static class TriggeredNotificationActionDto extends TriggeredActionDto {
 public enum NotificationActionType {
  WEBSOCKET, PUSH;
 }

 @JsonProperty("notificationType")
 @NotNull(message = "notificationType must not be blank!")
 private NotificationActionType notificationType;
}



@Data
@EqualsAndHashCode(callSuper = true)
public static class TriggeredDeviceActionDto extends TriggeredActionDto {
 @ApiModelProperty(example = "swagger001")
 @JsonProperty("deviceId")
 @NotNull(message = "Device id must not be blank!")
 private String deviceId;

 @ApiModelProperty(example = "1")
 @JsonProperty("channelId")
 @NotNull(message = "Channel id must not be blank!")
 @Range(min = 1, message = "Channel id must be a positive number")
 private int channelId;

 @ApiModelProperty(example = "1")
 @JsonProperty("value")
 @NotNull(message = "Value must not be blank!")
 private int value;

...
}


In the class, containing the TriggeredActionDto elements, I marked the list as @Valid, in order to force validation of the each elements of the list.


@JsonProperty("tasks")
@Valid
private List<TriggeredActionDto> tasks;



Tipp and tricks using Spring Data



Spring Data is a very comfortable way of defining DAO objects for your project. It can generate a DAO for your entity class, and provide all basic CRUD functions out of the box. You only need to define an interface, inherited from CrudRepository.

For more information of Spring Data basics I recommend reading following resources
  • http://projects.spring.io/spring-data
  • https://www.petrikainulainen.net/spring-data-jpa-tutorial/
It is however not always enough to use the basic functionality of Spring Data. I collect here some more interesting examples of using the possibilities of the framework.

Searching for String with prefix using Query


@Transactional
@Repository
public interface PushServiceConfigurationDao extends CrudRepository<PushSecrviceConfiguration, String> {

@Query(value = "SELECT c.value FROM PushSecrviceConfiguration c where c.key = UPPER(CONCAT('GOOGLE_GCM_API_KEY_', :appName))")
public String findGmcAuthKeyByAppName(@Param("appName") String appName);
}

Get record count


@Query(value = "SELECT COUNT(l) FROM Logic l where l.enabled = true AND l.gateway.id = :gatewayId")
int numberOfEnabledLogicsByGatewayId(@Param("gatewayId") String gatewayId);

Using enum as search parameter


@Query(value = "SELECT t FROM Logic t where t.gateway.id = :gatewayId and t.logicType = :logicType")
List<Logic> findAllByGatewayIdAndLogicType(@Param("gatewayId") String gatewayId, @Param("logicType") LogicType logicType);

Using @EntityGraph to control eager loading of elements


Defining the entitygraph in your domain class


@NamedEntityGraphs({
 @NamedEntityGraph(name = "graph.gateway.authTokens", attributeNodes = @NamedAttributeNode("authTokens")),
 @NamedEntityGraph(name = "graph.gateway.devices", attributeNodes = @NamedAttributeNode("devices"))
})
public class Gateway implements java.io.Serializable { ...

Using @EntityGraph annotation in your query

@EntityGraph(value = "graph.gateway.authTokens", type = EntityGraphType.LOAD)
Gateway findByDeviceCode(String deviceCode);

Defining native update command


@Modifying
@Query(value = "UPDATE ws_message_queue SET processor_id = ?2 WHERE backend_ip = ?1 AND processor_id is null", nativeQuery = true)
int reserveMessagesForProcessing(String backendIp, String processorId);


2017. október 5., csütörtök

Custom validator for REST parameter in Spring Boot


Using Spring boot applications, it is very easy to let the Spring framework to do the validation of the REST input parameter. You only need to add the corresponding validation annotations to the properties of the parameter class, and mark the parameter with @Valid annotation in the method header.


@RequestMapping(value = "/register", method = { RequestMethod.POST })
public RestResponse register(HttpServletRequest httpServletRequest, 
       @Valid @RequestBody PushRegistrationRequest registrationRequest) {



In case of your REST input object is validated with the @Valid annotation, most of the time, it is enough to  use default validations, like @NotNull, @Pattern, @Size, etc. Sometimes though you need to do more complex validations, considering multiple properties. To achieve this, you need to write your own annotation, and a corresponding validation class.

The annotation looks like this:


@Target({ ElementType.TYPE, ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Constraint(validatedBy = { HasCorrectAppIdValidator.class })
public @interface HasCorrectAppId {
 String message() default "App id is incorrect";

 Class<?>[] groups() default {};

 Class<? extends Payload>[] payload() default {};
}

  As you can see above, in the validatedBy attribute, you can define a validation class. the validator class needs to implement the javax.validation.ConstraintValidator interface.


import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;

public class HasCorrectAppIdValidator implements ConstraintValidator<HasCorrectAppId, PushRegistrationRequest> {

 @Override
 public void initialize(HasCorrectAppId constraintAnnotation) {
  // do nothing
 }

 @Override
 public boolean isValid(PushRegistrationRequest value, ConstraintValidatorContext context) {
  if (IOS.equals(value.getOs()) && value.getAppId().length() != 64) {
   String errorMessage = "length must be 64 for " + ClientOperationSystem.IOS;
   createErrorInContext(context, errorMessage);
   return false;

  } else if (ANDROID.equals(value.getOs()) && value.getAppId().length() < 65) {
   String errorMessage = "length must be greater than 65 for " + ClientOperationSystem.ANDROID;
   createErrorInContext(context, errorMessage);
   return false;
  }
  return true;
 }

 private void createErrorInContext(ConstraintValidatorContext context, String errorMessage) {
  context.disableDefaultConstraintViolation();
  context.buildConstraintViolationWithTemplate(errorMessage)
    .addPropertyNode("appId")
    .addConstraintViolation();
 }
}


That's it. In order to use tell to the framework to use the validator is, to annotate the parameter class with the new annotation.




@HasCorrectAppId
public class PushRegistrationRequest implements Serializable {
    ...
}


2017. szeptember 15., péntek

Using @ElementCollection in Spring JPA queries


In my domain model, I had a list of Strings to be stored. As it is a typical reason of using element collections, I decided to do so.

Using element collection in the domain model has the following advantages:
  • The domain model remains simple. No additional type, 
  • The connected list is bounded to the "master" entity. You do not need to take care of the maintenance of the elements by defining cascade type
  • The data was static, so only read from database was needed, therefore creating a one to many connection seemed not necessary. 
  • It is even possible to define an enumeration as type of the element collection. It gives the possibility to store only predefined values in the field.
My entity class looks like this:

@SuppressWarnings("serial")
@Entity
@Table(name = "SMART_HOME_SUBSCRIPTION")
@Data
public class SmartHomeSubscription implements Serializable {

 @Id
 @Column(name = "ID", unique = true, nullable = false, length = 36)
 private String id;

 @Column(name = "NAME", nullable = false, unique = true, length = 20)
 private String name;

 @ElementCollection(fetch = FetchType.EAGER)
 @CollectionTable(name = "ADDON", joinColumns = @JoinColumn(name = "SMART_HOME_SUBSCRIPTION_ID"))
 @Column(name = "NAME")
 private Set<String> addonNames = new HashSet<>();

 @ElementCollection(targetClass = AllowedFunction.class, fetch = FetchType.EAGER)
 @CollectionTable(name = "ALLOWED_FUNCTION", joinColumns = @JoinColumn(name = "SMART_HOME_SUBSCRIPTION_ID"))
 @Column(name = "NAME")
 @Enumerated(EnumType.STRING)
 private Set<AllowedFunction> allowedFunctions = new HashSet<>();
}

So how it is possible to use these element collections in queries in Spring JPA repository?

As you can see, the items of the element collection with String and annotated type can be used simple as Strings in the query. Equal and IN operator can be used to them such as for normal String fields.    


 @Query(value = "SELECT count(s) FROM SmartHomeSubscription s INNER JOIN s.allowedFunctions f INNER JOIN s.addonNames a WHERE f = :allowedFunction AND a IN :addonNames")
 public int getNumberOfAddonsValidForFunction(@Param("allowedFunction") AllowedFunction allowedFunction,
   @Param("addonNames") List<String> addonNames);










2017. szeptember 14., csütörtök

Create Spring service used only in test environment

Create Spring service used only in test environment

In my project, we use three different environments for running the application.
  • Production
  • SIT (system integration)
  • Local development
In the production environment thee is a third party system, that authenticates the user and automatically adds a header value to the request.

I wanted to implement a feature, which always requires the authentication information. So I needed to add mocked information into the REST request header in SIT and Local development environment.

I used a Service to process the request, and created additional subclasses for Local development and SIT environments. The subclasses must not be annotated as service. Otherwise you get exception at startup, marking that your service class in not unique.

The configuration of my local development environment looks like this:

@Configuration
@EnableScheduling
@EnableAsync
@EnableAspectJAutoProxy
@EnableTransactionManagement
@Profile("backend_localdev")
@EnableConfigurationProperties(DaoConfiguration.class)
public class BackendConfigurationLocalDev extends BackendConfiguration {

 @SuppressWarnings("unused")
 @Autowired
 private DaoConfiguration daoConfiguration;

 @Bean(value = "crbService")
 public CrbService getCrbService() {
  return new CrbServiceLocalDev();
 }
}


In order to add header values to the REST request, I implemented a HttpServletRequestWrapper class.

My service for local development looks like this:


public class CrbServiceLocalDev extends CrbService {

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

 private static final String HARDCODED_CRB_USER_STATUS_HEADER_VALUE = "{\"key\":\"value\"}";

 @Override
 public CrbUserInfo createCrbUserInfo(HttpServletRequest request) {
  log.warn("Entering CrbServiceLocalDev.createCrbUserInfo(). Must be used only for local development");

  HttpServletRequestWrapper wrapper = new LocalDevHttpServletRequestWrapper(request);
  return super.createCrbUserInfo(wrapper);
 }

 private class LocalDevHttpServletRequestWrapper extends HttpServletRequestWrapper {

  public LocalDevHttpServletRequestWrapper(HttpServletRequest request) {
   super(request);
  }

  @Override
  public String getHeader(String name) {

   if (StringUtils.isBlank(name)) {
    return super.getHeader(name);
   }

   final String value = getRequest().getParameter(name);
   if (!StringUtils.isBlank(value)) {
    return value;
   }

   if (MobileAppCrbUserStatus.HEADER_PARAM_X_CRB_USERSTATUS.equals(name)) {
    log.warn("Hardcoded userstatus header value is returned: {}", HARDCODED_CRB_USER_STATUS_HEADER_VALUE);
    return HARDCODED_CRB_USER_STATUS_HEADER_VALUE;
   }

   return super.getHeader(name);
  }
 }

}



2017. augusztus 29., kedd

Setting up a convenient Eclipse working environment


Here I would like to list all task, I need to do when setting up my Eclipse environment


Plug-ins to be installed
  • More Unit - the best tool for generating and maintaining unit test created for Eclipse 
  • JRebel - in case of server side programming, you can save a huge amount of time with it. It is commerctal, but a community version also can be used. This version is full featured, only sends messages sometimes to your Facebook wall. 
  • Lombok - enhances the Java language with annotation based elements, bringing it closer to the features of Scala, and other modern, Java-like languages. I suse it to avoid coding boilerplate code. You can generate getter/setter, toString, etc. 
  • Findbugs - static code analysis tool
  • PMD - static code analysis tool
  • Ucdetector - detects unnecesary code in your application. Also can be used to lower the accessibility of your classes or elements.
  • JIRA connector 
  • Eclipse class decompiler
  • InstaSearch - makes searching way faster with Lucence based search engine. 
  • QuickRex - evaluating Regular expressions directly in Eclipse
Settings to be made
  • add source to java packages
  • set toString generation
  • set formatter
  • set comparison to ignore white spaces by default
  • set multi monitor environment. Do not forget to stop Eclipse always with File/Exit, instead of closing any of the windows.
  • import your collection of short-keys 

Export your environment

Using prototype in Spring singleton service



I wanted to use a Spring bean, with private fields in order to build an object. Previously the builder class was really as an example of the builder pattern implemented. It was able to build the required object based on the parameters, defined for the builder.

Later on, after the requirement changed, the builder had to use other services in order to get detailed information for the build process. In this case you have the following possibilities:
  • define all services as parameter of the build process, and use them when needed.
    I did not choose this option, as it would not have resulted a clear interface for the builder. The dependent services are mandatory for the build process, but the builder can not force to define them in its interface. So the client has to set up the builder correctly before using it. It would have resulted such a restriction, what I did not want to build into my system.
  • Implement the builder as a Spring singleton bean. In this case the singleton must not have a state, so it is not possible to define the build parameters as field of the bean. It would make the implementation less readable, while the parameters must have been passed to the private methods several times.
So I chose to concert my builder class into a Spring prototype bean. The necessary parameters must be set by the client, but the necessary services are injected with CDI by the container.

The result looked like this:


@Service(value = "logicBuilderService")
@Scope("prototype")
public final class LogicBuilderService {

 @Autowired
 private DeviceDAO deviceDao;

 @Autowired
 private SupportedDeviceDao supportedDeviceDao;

 // contains eagerly initialized device and channel collection
 @Setter
 private Gateway gateway;

 @Setter
 private LogicRequest request;

 public Logic build() {
  Logic logic = createNewLogic();
  addTrigger(logic);
  addActions(logic);

  return logic;
 }
....


At the client side, you need to use an Objectfactory, in order to get a new instance of the service. Whenever you need a new, clean instance of the builder, you get it from the Spring framework, without the properties set.


 @Autowired
 private ObjectFactory<LogicBuilderService> prototypeFactory;

 private LogicBuilderService getNewLogicBuilderServiceInstance(Gateway gateway, LogicRequest request) {
  LogicBuilderService logicBuilder = prototypeFactory.getObject();
  logicBuilder.setGateway(gateway);
  logicBuilder.setRequest(request);

  return logicBuilder;
 }

In order to use the LogicBuilderService in a unit test, you need to mock the ObjectFactory, so it returns a new instance of the builder for all calls.


@Mock
 private ObjectFactory<LogicBuilderService> prototypeFactory;

 @InjectMocks
 private LogicRestService logicRestService;

 @Before
 public void setup() {
  when(prototypeFactory.getObject()).thenReturn(new LogicBuilderService());
 }