2016-12-30

Convert public certificate to Base64

String base64Encoded = Base64.encodeToString(pubkey.getEncoded(), Base64.DEFAULT).
    replaceAll("\n", "");

2016-12-29

Testy logów z log4j

Tworzymy klasę w /src/test/java/pakiet
import org.apache.log4j.AppenderSkeleton;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.apache.log4j.spi.LoggingEvent;

import java.util.ArrayList;
import java.util.List;

public class LogsHistorySaver extends AppenderSkeleton {
    private List logs;

    public void setUp() {
        logs = new ArrayList<>();
        Logger.getRootLogger().addAppender(this);
    }

    public void tearDown() {
        Logger.getRootLogger().removeAppender(this);
    }

    public List getLogs() {
        return logs;
    }

    @Override
    protected void append(LoggingEvent event) {
        logs.add(new Event(event.getLevel(), String.valueOf(event.getMessage())));
    }

    @Override
    public void close() {

    }

    @Override
    public boolean requiresLayout() {
        return false;
    }

    public class Event {
        private Level level;
        private String message;

        Event(Level level, String message) {
            this.level = level;
            this.message = message;
        }

        public Level getLevel() {
            return level;
        }

        public String getMessage() {
            return message;
        }

        @Override
        public String toString() {
            final StringBuilder sb = new StringBuilder("Event{");
            sb.append("level=").append(level);
            sb.append(", message='").append(message).append('\'');
            sb.append('}');
            return sb.toString();
        }
    }
}
I korzystamy w niej w teście w spoób następujący:
public class KaboomTest {

    private Kaboom sut;

    private LogsHistorySaver logsHistorySaver = new LogsHistorySaver();

    @Before
    public void setUp() throws Exception {
        logsHistorySaver.setUp();
    }

    @Test
    public void log() throws Exception {
        //when
        sut.build();

        //then
        List logs = logsHistorySaver.getLogs();

        assertThat(logs.size()).isEqualTo(3);
        assertThat(logs.get(0).getLevel()).isEqualTo(Level.INFO);
        assertThat(logs.get(0).getMessage()).isEqualTo("First log");
        assertThat(logs.get(1).getLevel()).isEqualTo(Level.INFO);
        assertThat(logs.get(1).getMessage()).isEqualTo("Second log");
        assertThat(logs.get(2).getLevel()).isEqualTo(Level.INFO);
        assertThat(logs.get(2).getMessage()).isEqualTo("Third log");
    }
}

2016-12-28

Mockito - mock final class

Mockito w wersji 2.4.2 umożliwia mockowanie finalnych klas (oraz metod).

Wystarczy dodać plik
src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker
zawierający jedną linię tekstu:
mock-maker-inline
Maven dependency:

    org.mockito
    mockito-core
    2.4.2

Stream zamiast forEach

Bez użycia streama (trzeba definiować listę obiektów):
private List buildTransactions(AccountNumber accountNumber) {
    List transactions = new ArrayList<>();
    accountNumber
        .getAccountHistoryList()
        .forEach(accountHistory -> transactions.add(transactionBuilder.build(accountHistory)));

    return transactions;
}
Używając streama możemy tworzenie listy obiektów pominąć:
private List buildTransactions(AccountNumber accountNumber) {
    return accountNumber
        .getAccountHistoryList()
        .stream()
        .map(accountHistory -> transactionBuilder.build(accountHistory))
        .collect(Collectors.toList());
}
Update: Można jeszcze bardziej elegancko:
private List buildTransactions(AccountNumber accountNumber) {
    return accountNumber
        .getAccountHistoryList()
        .stream()
        .map(transactionBuilder::build)
        .collect(Collectors.toList());
}

Optional.ofNullable().orElseThrow()

Przykład wykorzystania klasy Optional dostępnej od Java 8.

Bez Optionala
public void test(Task task) throws VerificationException {
    if (task.getCustomer() == null) {
        logger.error(CUSTOMER_NOT_FOUND);
        throw BmVerificationException.badRequest(CUSTOMER_NOT_FOUND);
    }
}
Z Optionalem
public void test(Task task) throws VerificationException {
    Optional.ofNullable(task.getCustomer()).orElseThrow(this::getException);
}

private VerificationException getException() {
    logger.error(CUSTOMER_NOT_FOUND);
    return VerificationException.badRequest(CUSTOMER_NOT_FOUND);
}

2016-12-27

AssertJ - assertThatExceptionOfType

Przykład alternatywnego testowania wyjątku - assertThatExceptionOfType
public class FooTest {

    @Rule
    public MockitoRule mockitoRule = MockitoJUnit.rule();

    @Mock
    private Validator validator;

    @InjectMocks
    private Foo sut;

    private HistoryRequest historyRequest;

    @Before
    public void setUp() throws Exception {
        historyRequest = new HistoryRequest();
    }

    @Test
    public void getHistoryThrowsExceptionDueToAccessDenied() throws Exception {
        when(validator.validate(historyRequest)).thenReturn(new Client());

        assertThatExceptionOfType(BloggerException.class)
                .isThrownBy(() -> sut.getHistory(historyRequest))
                .withMessage("Access denied");
    }
}

2016-12-20

GSON - ignorowanie pól przy pomocy własnej adnotacji

Tworzymy własną adnotację:

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Exclude {
}

Klasę implementującą ExclusionStrategy:

import com.google.gson.ExclusionStrategy;
import com.google.gson.FieldAttributes;

public class AnnotationExclusionStrategy implements ExclusionStrategy {

    @Override
    public boolean shouldSkipField(FieldAttributes f) {
        return f.getAnnotation(Exclude.class) != null;
    }

    @Override
    public boolean shouldSkipClass(Class clazz) {
        return false;
    }
}

Wykorzystujemy utworzoną adnotację w POJO:

public abstract class ExampleRequest {

    protected Long requestTime;
    protected String clientCode;
    @Exclude
    protected String hash;
}

Budujemy gsona np w taki sposób:

public class TestFacade {
    private static final Gson GSON;

    static {
        JsonDeserializer longToDateAdapter = (json, typeOfT, context) -> new Date(json.getAsJsonPrimitive().getAsLong());
        GSON = new GsonBuilder()
                .setDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ")
                .registerTypeAdapter(Date.class, longToDateAdapter)
                .setExclusionStrategies(new AnnotationExclusionStrategy())
                .create();
    }
}
Najważniejsza w tym przykładzie jest metoda setExclusionStrategies(new AnnotationExclusionStrategy()) dzięki której cała magia działa. źródło: http://stackoverflow.com/a/27986860/767529

2016-06-24

Git z konsoli

Podstawowe polecenia

źródło: http://zeroturnaround.com/

Dodatkowe polecenia

Usunięcie lokalnego brancha

git branch -d the_local_branch

Log w postaci drzewa

git log --graph --decorate --oneline
git log --graph --full-history --all --color --pretty=format:"%x1b[31m%h%x09%x1b[32m%d%x1b[0m%x20%s"

Definiowanie własnych aliasów

git config --global alias.tree "log --graph --full-history --all --color --pretty=format:\"%x1b[31m%h%x09%x1b[32m%d%x1b[0m%x20%s\""

2016-05-10

Tesseract pod Centos - JNA problem

Problem:

Caused by: java.lang.UnsatisfiedLinkError: /tmp/jna-1347637353/jna2637488223705099160.tmp: /tmp/jna-1347637353/jna2637488223705099160.tmp: failed to map segment from shared object: Operation not permitted
        at java.lang.ClassLoader$NativeLibrary.load(Native Method) [rt.jar:1.8.0_77]
        at java.lang.ClassLoader.loadLibrary0(ClassLoader.java:1941) [rt.jar:1.8.0_77]
        at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1824) [rt.jar:1.8.0_77]
        at java.lang.Runtime.load0(Runtime.java:809) [rt.jar:1.8.0_77]
        at java.lang.System.load(System.java:1086) [rt.jar:1.8.0_77]
        at com.sun.jna.Native.loadNativeDispatchLibraryFromClasspath(Native.java:851) [jna-4.2.2.jar:4.2.2 (b0)]
        at com.sun.jna.Native.loadNativeDispatchLibrary(Native.java:826) [jna-4.2.2.jar:4.2.2 (b0)]
        at com.sun.jna.Native.(Native.java:140) [jna-4.2.2.jar:4.2.2 (b0)]
        at net.sourceforge.tess4j.TessAPI1.(TessAPI1.java:41) [tess4j-3.1.0.jar:3.1.0]

Rozwiązanie problemu:

Taki problem występuje ponieważ katalog /tmp jest noexec. Są dwa sposoby na rozwiązanie tego problemu. Można usunąć noexec z /tmp albo zdefiniować inne miejsce zapisu dla tmp natywnych bibliotek. Ja wybrałem ten drugi sposób i ładnie działa. Wystarczy dopisać:

-Djava.io.tmpdir=/jakis_katalog/tmp

źródło: cloudbees.zendesk.com

2016-05-09

Java z automatyczną akceptacją licencji

Instalacja Java pod Ubuntu z automatyczną akceptacją licencji. Taka możliwość może być przydatna przy instalacji składników ze skryptu - np. przy stawianiu systemu w środowisku Docker'a (w Dockerfile).

echo "oracle-java8-installer shared/accepted-oracle-license-v1-1 select true" | sudo debconf-set-selections
sudo apt-get install -y oracle-java8-installer

2016-05-06

Git: aktualizacja listy branchy na lokalnej maszynie

# list all branches, local and remote
$ git branch -av

# update remote list
$ git remote update origin --prune

Instalacja Python 2.7.10 pod CentOS

yum install gcc
cd /usr/src
wget https://www.python.org/ftp/python/2.7.10/Python-2.7.10.tgz
tar xzf Python-2.7.10.tgz
cd Python-2.7.10
./configure
make altinstall

# python2.7 -V
Python 2.7.10

2016-05-02

Odpalenie curl'em POST'a

curl -i -H "Accept: application/json" -H "Content-type: application/json" -X POST -d '{}' http://test.pl/kabooom

2016-04-27

Docker: podstawowe polecenia

Lista lokalnych obrazów

Warto czasem zobaczyć jakie mamy obrazy na dysku:

$ docker images

REPOSITORY            TAG                 IMAGE ID            CREATED             SIZE
dpz/wildfly-blueocr   latest              22af6d6fe20c        41 hours ago        4.791 GB
dpz/opencv            latest              7124e8b011a8        41 hours ago        4.765 GB
dpz/wildfly           latest              00f0de2d3fdc        41 hours ago        1.397 GB
dpz/system            latest              f1ef0b164424        41 hours ago        1.098 GB
centos                7                   778a53015523        4 weeks ago         196.7 MB
trigsoft/wildfly      latest              a251fdfa8320        10 weeks ago        635.4 MB

Usunięcie obrazów i kontenerów

Pracując z Dockerem możesz natknąć się na problem z dużą liczbą obrazów i kontenerów. Aby je wszystkie usunąć jedną komendą wystarczy:

# Delete all containers
docker rm $(docker ps -a -q)
# Delete all images
docker rmi $(docker images -q)

Jeśli chcesz usunąć nieoznaczone obrazy wystarczy:

#!/bin/bash
# Delete untagged images (dangling)
docker rmi -f $(docker images -q --filter "dangling=true")

Wyszukiwanie obrazów

Wyszukiwanie obrazów z repo Dockera

$ docker search wildfly

NAME                         DESCRIPTION                                     STARS     OFFICIAL   AUTOMATED
jboss/wildfly                WildFly application server image                185                  [OK]
openshift/wildfly-8-centos   DEPRECATED - see openshift/wildfly-81-centos7   6                    [OK]
piegsaj/wildfly              WildFly 10.0.0.Final on Java 8                  4                    [OK]
centos/wildfly                                                               3                    [OK]
andreptb/wildfly             Debian Jessie based image with JBoss Wildf...   2                    [OK]
emedeiros/wildfly            WildFly 9.0.2.Final with OpenJDK 8              1                    [OK]
sewatech/wildfly             Debian + WildFly, in HA mode                    1                    [OK]
trigsoft/wildfly             WildFly 10.0.0 + Java 8 + PostgreSQL 9.4        1                    [OK]
ceagan/wildfly               JBoss Wildfly with XMLStarlet                   1                    [OK]
hpehl/wildfly-domain         WildFly domain with one domain controller ...   1                    [OK]
projectomakase/wildfly       Docker image for WildFly                        0                    [OK]
huggosantos/wildfly-mysql    wildfly-mysql                                   0                    [OK]
dthuilot/wildfly-admin       wildfly with admin console enabled.             0                    [OK]
huggosantos/wildfly           Wildfly version 9.0.2.Final                    0                    [OK]
khipu/wildfly                Wildfly 10 / openjdk 8 / alpine 3 and cust...   0                    [OK]
vereshus/wildfly             Wildfly application server with Java 8.         0                    [OK]
caltha/wildfly               Self contained WildFly application server       0                    [OK]
ifbaeunapolis/wildfly        wildfly                                         0                    [OK]
cnry/wildfly                 WildFly Application Server                      0                    [OK]
sledsoft/wildfly                                                             0                    [OK]
bitnami/wildfly              Bitnami WildFly Docker Image                    0                    [OK]
jamesnetherton/wildfly       A minimalistic Docker image for WildFly ru...   0                    [OK]
dcm4che/wildfly              wildfly based on 8-jre for dcm4che/archive 5    0                    [OK]
mihahribar/wildfly           Dockerfile for Wildfly running on Ubuntu 1...   0                    [OK]
dolphindev/wildfly           OpenDolphin application server created on ...   0                    [OK]

Pobieranie obrazu z repo

Aby pobrać przykładowe repo trigsoft/wildfly, na którym jest WildFly 10.0.0 + Java 8 + PostgreSQL 9.4 wystarczy użyć prostej komendy:

$ docker pull trigsoft/wildfly

Using default tag: latest
latest: Pulling from trigsoft/wildfly
a3ed95caeb02: Pull complete
a07226856d92: Pull complete
17a00fa8d5c0: Pull complete
132e3c60d9a9: Pull complete
f60acd56d870: Pull complete
271ea3c24483: Pull complete
0ad07189dd16: Pull complete
a3d975cb837d: Pull complete
d7102d6afcc6: Pull complete
688ac970b5ea: Pull complete
c30a372a098b: Pull complete
07c3dd598370: Pull complete
cf3cecce1b1d: Pull complete
b29101bafc07: Pull complete
Digest: sha256:a2c25fdbc4a37afa9c2ee559a3eceacbfe7128eacf0a5dc7c846f54542043ff3
Status: Downloaded newer image for trigsoft/wildfly:latest

źródło: techoverflow.net

2016-02-28

JavaEE - Annotation Type Schedule

Za pomocą adnotacji @Schedule istnieje możliwość odpalenia kawałka kodu w określonych odcinkach czasu - jest to coś podobnego do Cron'a na serwerach linuksowych.

Poniżej przestawiam przykład, w którym widać zastosowanie tej adnotacji - Metoda init() będzie uruchamiana co 5 minut.

package pl.marceen.schedule;

import org.apache.log4j.Logger;

import javax.ejb.Schedule;
import javax.ejb.Singleton;
import javax.ejb.Startup;

/**
 * @author Marcin Zaremba
 */
@Singleton
@Startup
public class ScheduleTest {

    private static final Logger logger = Logger.getLogger(ScheduleTest.class);

    @Schedule(persistent = false, hour = "*", minute = "*/5")
    public void init() {
        logger.info("Method init() started.");
    }

}

Więcej możliwościach tej adnotacji: docs.oracle.com