Adopting Builder Pattern with Abstract class

Builder Pattern helps simplify constructor and increase readability with fluent interface. It can also be handy to make the class immutable (not demonstrated here).
Here is an example if you have an abstract base class in the way:

The abstract base class:

public abstract class BaseClass {

private String name;

protected static abstract class BaseBuilder<T extends BaseClass, B extends BaseBuilder>{
  protected T actualClass;
  protected B actualClassBuilder;

  protected abstract T getActual();
  protected abstract B getActualBuilder();
  protected BaseBuilder() {
    actualClass = getActual();
    actualClassBuilder = getActualBuilder();
  }
  public B name(String name) {
    actualClass.setName(name); return actualClassBuilder;
  }
  public T build() { return actualClass; }
}

private void setName(String name) { this.name = name; }

private String getName() { return name; }

}

The concrete, extending class:

public class ConcreteClass extends BaseClass {
  public static class Builder extends BaseBuilder<ConcreteClass, Builder> { 

    public Builder anotherField(String anotherField) {
            actualClass.setAnotherField(anotherField);
            return this;
        }

        @Override
        protected ActionTask getTask() {
            return new ActionTask();
        }

        @Override
        protected Builder getBuilder() {
            return this;
        }
}

To use it:

ConcreteClass myConcreteObject =
  new ConcreteClass.Builder()
    .name("one")
    .anotherField("two")
    .build();
Advertisements

Mocking static Logger without PowerMock

Suppose you have a class that uses a static Logger to log some error, and you would like to unit test including the message logged. One approach is to use PowerMock because the Logger is usually declared static in your class. However for logging, you don’t need to add PowerMock to your dependency if you don’t already use it. Here’s an example:

public class MyClass {
private static final Logger LOGGER = Logger.getLogger(MyClass.class);
public void myMethod() {
try {
// ...
}
catch ( ... ) {
LOGGER.error("my error message");
}
}
}

 

@RunWith(MockitoJUnitRunner.class)
public class MyClassTest {
@Mock
private Appender logAppender;
@Captor
private ArgumentCaptor loggingEventArgumentCaptor = ArgumentCaptor.forClass(LoggingEvent.class);</code>

@Before
public void setUp() {
Logger logger = Logger.getLogger(ConfigBasedActionLookupService.class);
logger.addAppender(logAppender);
logger.setLevel(Level.INFO);
}

@Test
public void myMethod_invalidConditions_shouldLogError() {
verify(logAppender, times(1)).doAppend(loggingEventArgumentCaptor.capture());
LoggingEvent actualLoggingEvent = loggingEventArgumentCaptor.getValue();
assertThat(actualLoggingEvent, is(notNullValue()));
assertThat(actualLoggingEvent.getRenderedMessage(), containsString("my error message"));
}

Enable ping to your Windows on Parallel

I have Parallel 11 with Windows 10 installed on my Mac, but I was not able to ping the VM from my Mac. Here’s how to enable to guest machine:

on Windows, go to

Firewall > Advanced Settings > “Windows Firewall with Advanced Security on Local Computer”

> Windows Firewall Properties (link) > IPsec Settings (last tab) > Except ICMP from IPSec <— change to Yes.

To find out the ip address of your Windows VM, go to command prompt and type

ipconfig

you will get something like

IPv4 Address. . . . . . . . . . . : <your ip address>

Setting Up Vagrant CentOS 7 with Virtual Box Guest Additions

setting up vagrant centos7 with virtual box guest additions

Why Guest Additions?
– mount local hard drive to vm
– copy and paste between host and vm

Why VBox version 4.x when there’s 5.x?

I am on Mac OS X El Captian and VirtualBox 5.x didn’t work for me.

I installed VBox 5, setup CentOS7 through VBox’s GUI, and it fails to start with some “session” error.

I then installed VBox 4.30, and CentOS7 worked like a charm, EXCEPT I couldn’t get the Guest Addition running, nor could I get the bridged network / port forwarding working to allow me to ssh from Mac terminal to the VM.

So I head to vagrant boxes, which gives significant benefit for my use case beside it’s another option to try. I can skip the installation screen and get a centos up and running in minutes! I will need a few of those boxes, so not having to repeat installation is definitely a plus.

There are vagrant box that has guest addition preinstalled, but call me paranoid, I want to use the official centos7 image.

Once you have your centos box up by running these in your terminal

vagrant up
vagrant ssh

Run following script:

#!/bin/bash

# install virtualbox guest addition on centos VM

sudo yum -y update
sudo yum -y install wget kernel-headers-$(uname -r) kernel-devel gcc* 
cd /opt
sudo wget -c http://download.virtualbox.org/virtualbox/4.3.40/VBoxGuestAdditions_4.3.40.iso -O VBoxGuestAdditions_4.3.40.iso

cd /opt
sudo mount VBoxGuestAdditions_4.3.40.iso -o loop /mnt
cd /mnt
sudo sh VBoxLinuxAdditions.run --nox11


sudo reboot

 

To mount your drive permanently, add following line to Vagrant file

 config.vm.synced_folder "/hostpath", "/vmpath"

where “/hostpath” is the folder from my host that I want to share with the VM, and “/vmpath” is how I can access the shared folder from within the VM.

vagrant reload

vagrant up

vagrant ssh

You can now access the shared folder by going to your value set in “/vmpath”

Error running embedded tomcat with gradle – NoClassDef found for org.slf4j.spi.LoggerFactoryBinder

Problem

trying to run an embedded tomcat with the gradle tomcat plugin (https://github.com/bmuschko/gradle-tomcat-plugin)

gradle tomcatRun

but getting the following error:

Caused by: java.lang.ClassNotFoundException: org.slf4j.spi.LoggerFactoryBinder

Solution

likely your gradle is too new.

To resolve the issue, run with an older version of gradle using gradle wrapper.

generate gradle wrapper for your project

gradle wrapper --gradle-version 2.3

then run with

gradlew tomcatRun

 

Tested with

  • installed gradle 2.11
  • gradle wrapper 2.3
  • tomcat 7.0.11
  • windows

Exposing docker container ports in Windows

You might want to map a running docker container to your localhost’s port, but you can’t. For example, you run your image with

docker run -p 8080:8080 myImage

and expect to hit the docker container at http://localhost:8080 … but that doesn’t work.

In Windows, because Docker runs as a VM, it’s localhost refers to the VM’s localhost.

To find out the VM’s ipaddress, run this command

docker-machine ip default

sample output: 192.168.99.100

then you can access the image at http://192.168.99.100:8080

Encrypting your passwords in Java

Q: What are things that you need to use but should not be visible?

A: Air? Sure. And passwords!

Jasypt is a handy library to handle the encryption and decryption for you.

It has great integration with Spring and works well transparently with properties files via EncryptablePropertyPlaceholder.

Caching web content in Spring MVC Annotation Config

I support hosting static web resources (css/js/img/fonts/etc) outside of your web application, in a simple CDN (content distribution network) with a simple application server like nginx.

However, if your infrastructure does not exist, using these configs in your Spring MVC app would help greatly. This WebConfig class is the equivalent to web.xml.

@Configuration
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter
{
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry)
    {
        registry.addResourceHandler("/resources/**").addResourceLocations("/resources/").setCachePeriod(2592000);  // 30 days for internal
        registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/").setCacheControl(CacheControl.maxAge(365, TimeUnit.DAYS).cachePublic());  // 1 year for external
    }

WebJars is something we are trying out. It packages web resources into JARs and you can use them with maven / gradle as dependencies. I would still prefer CDN, but again, if you don’t have the infrastructure already setup, this seems like a good option.

tested with

Spring 4.2.5-RELEASE

Delaying message with Dead-Letter Exchange in RabbitMQ

You have a message that you tried processing, but say your dependencies aren’t available, and you would like to retry at a later time. So you N-ACK the message with requeue. A N-ACK by default requeue the message to the FRONT of the queue. So it would result in an immediate retry, which is not helpful. RabbitMQ does not provide out-of-the-box delaying mechanism.

To make the delay happen, you can make use of the dead-letter exchange. See the hack in following post:

http://blog.james-carr.org/2012/03/30/rabbitmq-sending-a-message-to-be-consumed-later/

C sharper with Extensions

Here’s another post to continue on the Java developer C# experience.

Extension classes, with naming convention of Extensions.cs

public enum Fruits {
  Apple,
  Banana,
  Orange
}

public static class FruitsExtensions {
  public static bool IsRed(this Fruits fruit) {
     return fruit == Fruits.Apple;
  }
}

this would allow you to do

var myfruit = Fruits.Apple;
myfruit.IsRed();

It looks like a Decorator pattern, except upon reading more, the extensions miss the dynamic properties of the design pattern – it cannot alter behaviors of the existing class. All it does is to provide a way to add static method to an existing class. So it is NOT a Decorator.

Again, the Visual Studio peek definition doesn’t help again. It shows the class with empty methods. A search for the entire project helped though. The code was embedded in a common class.