2020-03-19

How to install maven on macOS

I recommended use Homebrew to install maven:

brew install maven

2020-03-15

Przeniesienie statycznej strony do AWS S3

Od dłuższego czasu nosiłem się z zamiarem przejścia ze swoją stroną domową do AWS - tak dla nauki przez zabawę. Wspomniana strona (marceen.pl) jest prosta - wiele się tam nie dzieje. Jest co prawda formularz kontaktowy i mechanizm pobierający i wyświetlający wpisy z tego bloga. Postanowiłem jednak z tego wszystkiego zrezygnować. Dzięki temu strona mogła stać się statyczna i można było ją umieścić na AWS S3 bardzo niewielkim kosztem. Utrzymanie tej strony również będzie tańsze niż przy tradycyjnym hostingu. 

Kroki, które trzeba wykonać:

  1. Utworzenie potrzebnych bucket'ów na S3 oraz podpięcie do nich własnej domeny (Route53): https://docs.aws.amazon.com/AmazonS3/latest/dev/website-hosting-custom-domain-walkthrough.html#root-domain-walkthrough-add-record-to-hostedzone
  2. Utworzenie pipeline'a pomocnego przy wdrażaniu nowej wersji (CodePipeline): https://medium.com/@sithum/automate-static-website-deployment-from-github-to-s3-using-aws-codepipeline-16acca25ebc1

2020-02-22

Install java on macOS with allowing version switching

Installing with Homebrew

-- Updating brew:
brew update

-- Adding the casks tap:
brew tap homebrew/cask-versions

-- Adding AdoptOpenJDK (https://adoptopenjdk.net/ and https://github.com/AdoptOpenJDK/homebrew-openjdk):
brew tap adoptopenjdk/openjdk

-- Looking for java versions:
brew search java

-- Looking for AdoptOpenJDK versions:
brew search jdk

-- Checking the details on the java version that will be installed:
brew cask info java

-- Checking the details on the AdoptOpenJDK version that will be installed:
brew cask info jdk

-- Installing current version java:
brew cask install java

-- Installing specific version of AdoptOpenJDK:
brew install --cask adoptopenjdk12

Where is my java?

/usr/libexec/java_home -V

Switching java version using .bash_profile:

export JAVA_8_HOME=$(/usr/libexec/java_home -v1.8)
export JAVA_9_HOME=$(/usr/libexec/java_home -v9)
export JAVA_10_HOME=$(/usr/libexec/java_home -v10)
export JAVA_11_HOME=$(/usr/libexec/java_home -v11)
export JAVA_12_HOME=$(/usr/libexec/java_home -v12)
export JAVA_13_HOME=$(/usr/libexec/java_home -v13)

alias java8='export JAVA_HOME=$JAVA_8_HOME'
alias java9='export JAVA_HOME=$JAVA_9_HOME'
alias java10='export JAVA_HOME=$JAVA_10_HOME'
alias java11='export JAVA_HOME=$JAVA_11_HOME'
alias java12='export JAVA_HOME=$JAVA_12_HOME'
alias java13='export JAVA_HOME=$JAVA_13_HOME'

# default to Java 13
java13
source: https://stackoverflow.com/questions/52524112/how-do-i-install-java-on-mac-osx-allowing-version-switching

Installing Java17

source: https://java.tutorials24x7.com/blog/how-to-install-openjdk-17-on-mac

2020-02-19

iterm2: setting keyboard shortcuts to jump to beginning/end of line

Add new keyboard shortcut in Preferences > Profiles > Keys:
FOR  ACTION         SEND
⌘←  "SEND HEX CODE" 0x01 
⌘→  "SEND HEX CODE" 0x05
⌥←  "SEND ESC SEQ"  b
⌥→  "SEND ESC SEQ"  f

2020-01-12

pgAdmin4 on Docker - exporting and importing Servers

Export:

get container id:
docker ps

dump server list:
docker exec -it {container id} python setup.py --dump-servers servers.json --user {user}

get server list:
docker cp {container id}:/pgadmin4/servers.json servers.json

Import:

launch pgadmin:
docker run -p 801:80 --name pgadmin \
-e "PGADMIN_DEFAULT_EMAIL={user}" \
-e "PGADMIN_DEFAULT_PASSWORD={pass}" \
-d dpage/pgadmin4

get container id:
docker ps

copy server list into container:
docker cp {container id}:/tmp/servers.json

import server list:
docker exec -it {container id} python setup.py --load-servers servers.json --user {user}

source: https://www.pgadmin.org/docs/pgadmin4/latest/import_export_servers.html

2018-06-12

Rounding BigDecimal into scale 2 in WebService

BigDecimalConverter class:
final class BigDecimalConverter {
    private final static Logger logger = LoggerFactory.getLogger(BigDecimalConverter.class);

    private static final int SCALE = 2;

    static String convertToString(BigDecimal bigDecimal) {
        if (bigDecimal == null) {
            return null;
        }

        logger.info("Rounding bigDecimal {} into scale {}", bigDecimal, SCALE);
        return bigDecimal.setScale(SCALE, RoundingMode.HALF_UP).toString();
    }
}
BigDecimalXmlAdapter class:
public class BigDecimalXmlAdapter extends XmlAdapter {
    private final static Logger logger = LoggerFactory.getLogger(BigDecimalXmlAdapter.class);

    @Override
    public BigDecimal unmarshal(String s) {
        logger.info("Unmarshal String: {}", s);

        try {
            return new BigDecimal(s);
        } catch (NumberFormatException e) {
            return null;
        }
    }

    @Override
    public String marshal(BigDecimal bigDecimal) {
        logger.info("Marshal BigDecimal {}", bigDecimal);

        return BigDecimalConverter.convertToString(bigDecimal);
    }
}
package-info.java file:
@javax.xml.bind.annotation.XmlSchema(namespace = "http://app.host.pl/api/types", elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED)
@javax.xml.bind.annotation.adapters.XmlJavaTypeAdapters({
        @javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter(value = pl.marceen.soap.control.BigDecimalXmlAdapter.class, type = java.math.BigDecimal.class)
})
package pl.host.app.api.types;

2018-04-04

How to examine PostgreSQL server's SSL certificate?

Save script info file postgres_get_server_cert.py
#!/usr/bin/env python

import argparse
import socket
import ssl
import struct
import subprocess
import sys
import urlparse


def main():
    args = get_args()
    target = get_target_address_from_args(args)
    sock = socket.create_connection(target)
    try:
        certificate_as_pem = get_certificate_from_socket(sock)
        print certificate_as_pem
    except Exception as exc:
        sys.stderr.write('Something failed while fetching certificate: %s' %
            exc.message)
        sys.exit(1)
    finally:
        sock.close()


def get_args():
    parser = argparse.ArgumentParser()
    parser.add_argument('database', help='Either an IP address, hostname or'
        ' URL with host and port')
    return parser.parse_args()


def get_target_address_from_args(args):
    specified_target = args.database
    if '//' not in specified_target:
        specified_target = '//' + specified_target
    parsed = urlparse.urlparse(specified_target)
    return (parsed.hostname, parsed.port or 5432)


def get_certificate_from_socket(sock):
    request_ssl(sock)
    ssl_context = get_ssl_context()
    sock = ssl_context.wrap_socket(sock)
    sock.do_handshake()
    certificate_as_der = sock.getpeercert(binary_form=True)
    certificate_as_pem = encode_der_as_pem(certificate_as_der)
    return certificate_as_pem


def request_ssl(sock):
    # 1234.5679 is the magic protocol version used to request TLS, defined
    # in pgcomm.h)
    version_ssl = postgres_protocol_version_to_binary(1234, 5679)

    packet = '%(length)s%(version)s' % {
        'length': struct.pack('!I', 8),
        'version': version_ssl,
    }
    sock.sendall(packet)
    data = read_n_bytes_from_socket(sock, 1)
    if data != 'S':
        raise Exception('Backend does not support TLS')


def get_ssl_context():
    # Return the strongest SSL context available locally
    for proto in ('PROTOCOL_TLSv1_2', 'PROTOCOL_TLSv1', 'PROTOCOL_SSLv23'):
        protocol = getattr(ssl, proto, None)
        if protocol:
            break
    return ssl.SSLContext(protocol)


def encode_der_as_pem(cert):
    # Forking out to openssl to not have to add any dependencies to script,
    # preferably you'd do this with pycrypto or other ssl libraries.
    cmd = ['openssl', 'x509', '-inform', 'DER']
    pipe = subprocess.PIPE
    process = subprocess.Popen(cmd, stdin=pipe, stdout=pipe, stderr=pipe)
    stdout, stderr = process.communicate(cert)
    if stderr:
        raise Exception('openssl errored when converting cert to PEM: %s' %
            stderr)
    return stdout.strip()


def read_n_bytes_from_socket(sock, n):
    buf = bytearray(n)
    view = memoryview(buf)
    while n:
        nbytes = sock.recv_into(view, n)
        view = view[nbytes:] # slicing views is cheap
        n -= nbytes
    return str(buf)


def postgres_protocol_version_to_binary(major, minor):
    return struct.pack('!I', major << 16 | minor)


if __name__ == '__main__':
    main()
Save certificate into file cert.txt
postgres_get_server_cert.py example.com:5432 | openssl x509 > cert.txt
Check certificate dates:
postgres_get_server_cert.py example.com:5432 | openssl x509 -noout -dates
Check full certificate:
postgres_get_server_cert.py example.com:5432 | openssl x509 -noout -text
source:

2018-02-14

How to make mock to void methods with Mockito

Call Real Method

Mock not void method:
Mockito.when(jsonResponseValidator.validate(any(DefaultResponse.class))).thenCallRealMethod()
Mock void method:
Mockito.doCallRealMethod().when(jsonResponseValidator).validate(any(DefaultResponse.class));
You can use any of the doReturn(), doThrow(), doAnswer(),doNothing(), doCallRealMethod() family of methods.

Do Throw

Mock void method with doThrow():
...

@Mock
privare TransferSender transferSender;

...
Transfer transfer = new Transfer();
Mockito.doThrow(new MyException("kabooom!").when(transferSender).send(transfer);
source: Mockito API

2017-10-06

JavaEE - wyświetlenie całego URI za pomocą UriInfo

UriInfo (za pomocą którego jest możliwe wyciągnięcie całego URI) można wstrzyknąć za pomocą adnotacji @Context jako pole klasy:
package pl.marceen.test.boundary;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.ejb.Stateless;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.UriInfo;

@Stateless
@Path("test")
public class TestRestReceiver {
    private final static Logger logger = LoggerFactory.getLogger(TestRestReceiver.class);

    @Context
    private UriInfo uriInfo;

    @GET
    @Path("logStatus")
    public String logStatus() {
        logger.info("Path: {}", uriInfo.getAbsolutePath());

        return "OK";
    }
}
Można wstrzyknąć UriInfo również jako atrybut metody:
package pl.marceen.test.boundary;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.ejb.Stateless;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.UriInfo;

@Stateless
@Path("test")
public class TestRestReceiver {
    private final static Logger logger = LoggerFactory.getLogger(TestRestReceiver.class);

    @GET
    @Path("logStatus")
    public String logStatus(@Context UriInfo uriInfo) {
        logger.info("Path: {}", uriInfo.getAbsolutePath());

        return "OK";
    }
}

2017-01-16

Centos6 - add and remove User

Add User

sudo adduser newuser
sudo passwd newuser

Delete User

sudo userdel -r newuser
You can add the flag “-r” to the command if you would like to simultaneously remove the users’s home directory and files.

2017-01-11

EntityManager - find list of objects

public List<Element> findAllElements(Task task) {
    logger.info("Try to find elements - task: {}", task.getId());

    return em.createNamedQuery(Element.FIND_ALL_BY_TASK, Element.class)
               .setParameter("task", task)
               .getResultList();
}

2016-12-30

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