Donnerstag, 30. August 2018

GIT Troubleshooting - revert and pull not possible?

Sometimes a file does not differ from the repository version. But GIT shows it as modified and does not accept a revert.

This file, however should not be commited, because it has not changed, but is simply not properly managed by GIT.

This is related to GIT working in file mode.

Try this and then pull again:

$git config core.fileMode false

Donnerstag, 19. Juli 2018

A nice true story about making a difference - Revisiting Michael

Dear reader,

This post is not about technology or frameworks. It is rather focused on the most important thing we have: the people who surround us and how we influence them and how they influence us.

About ten years ago I worked as a Teamleader for a large software company in Germany.
We were hiring developers, but the interviews were quite frustrating. We did simply not find the person we were looking for. Because what we needed at this time was a Can-Do attitude. This was of vital importance, because we had deadlines approaching and were lacking the possibility to change them or release some pressure which was inflicted upon the team. So we needed someone who was positive, eager to learn and willing to go the extra mile.

Michael was someone whom I knew from University. He was unsure about his direction in life but at the same time I saw a lot of potential in him. So I asked him to come by and do a job interview with me. I wanted to hire him and so I did. He was unsure if he would be able to cope with the challenges which were waiting for him but much to my enjoyment, he agreed to work with us.

During the first project we did for a large logistics company in Germany (market leader), he approached me by saying that he would not be able to make it. I knew that the whole situation was challenging for him - even demanding. But I insisted on my view: I told him that I saw great potential and that for him, it was rather about self-confidence but about technical skillsets. He stayed with us. Project was a success. We met the deadline.

Today, a colleage of mine approached me and asked me if I knew this guy (he was talking about Michael). I said yes. The colleague, Frank, said that Michael would send me warm-hearted greetings. He is working with him at the same consulting company (Top 5 in Germany) and he is really good at his job. Considering that I pursued Michael to stay and overcome all obstacles, to become a great software developer (which he is by now), I feel very good. I really wanted to share this story with you because this is how we make a difference.

By encouraging and coaching a person, we can help this person to change her or his mindset from "I am afraid" to "I can do it". we can help to build up self-confidence.
So this person will eventually be able to pursue higher goals and become what he or she wants to be.

And how good is that? ;)

Best,
Tim

Dienstag, 15. Mai 2018

Java: How to do SSL, Basic Authentication and log Request Response in XML/JSON with Jersey JAX WS RS Client

//Example with XML, SSL, Basic Auth


import java.io.InputStream;
import java.security.KeyStore;
import java.security.NoSuchAlgorithmException;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.ClientResponseFilter;
import javax.ws.rs.client.WebTarget;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.glassfish.jersey.client.ClientConfig;
import org.glassfish.jersey.client.ClientProperties;

import com.mycompany.exception.MyException;

/**
 *         Purpose of this class is to use jersey/jaxb related connection to an external API via REST WS.
 */
public class RestClient {

    private static final Logger LOG = LogManager.getLogger(RestClient.class);


    private int connectTimeout = 30000;
    private int readTimeout = 30000;
   
private String uri;   
    protected WebTarget service;
    protected MyConfiguration config;
    private Client client;

     public void initialize() throws MyException {
        if (uri == null || uri.trim().isEmpty()) {
            uri = "https://myapi";
        }

        if (!(uri != null && !uri.trim().isEmpty())) {
            throw new MyException("[x] uri wrong: " + uri);
        }

        ClientBuilder builder = ClientBuilder.newBuilder();
        String proxy = "172.00.00.00:1234";
        if (proxy != null) {
            ClientConfig clientConfig = new ClientConfig();
            clientConfig.property(ClientProperties.PROXY_URI, proxy);
            builder = builder.withConfig(clientConfig);
        }
        builder = builder.sslContext(initializeHttpClientWithKeyStoreAndCert());

        client = builder.build();
        client.property(ClientProperties.CONNECT_TIMEOUT, connectTimeout);
        client.property(ClientProperties.READ_TIMEOUT, readTimeout);

        client.register((ClientResponseFilter) (requestContext, responseContext) -> responseContext.getHeaders()
                .putSingle("Content-Type", "application/xml"));

        client.register(new EntityLoggingFilter());

        service = client.target(uri);
        LOG.debug("RestClient initialized.");
    }

    private TrustManager[] getTrustManager() throws Exception {
        try (InputStream inputStream = getClass().getClassLoader().getResourceAsStream("com/mycompany/my_keystore.jks")) {
            KeyStore keyStore = KeyStore.getInstance("JKS");
            keyStore.load(inputStream, "somepassword".toCharArray());
            TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance("PKIX");
            trustManagerFactory.init(keyStore);
            TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
            return trustManagers;
        }
    }

    private SSLContext initializeHttpClientWithKeyStoreAndCert() throws MyException {
        try {

            SSLContext sslContext = SSLContext.getInstance("SSL");
            try {
                sslContext.init(null, getTrustManager(), null);
            } catch (Exception e) {
                throw new MyException("[x] Failed to create SSL Context. ", e);
            }

            return sslContext;

        } catch (NoSuchAlgorithmException e) {
            LOG.error(e);
            throw new MyException(e.getClass().getSimpleName() + " while Creating HttpClient: " + e.getMessage(), e);
        }
    }

}



==============  POST a request POJO =====================

    public MyResponsePOJO postRequest(MyRequestPojo myrequestPojo) {
       

        // credentials shown for teaching purpose. Usually they are stored in a properties file or config.
        String basicAuthUser = "someUser";
        String basicAuthPass = "somePassword";
        String base64Creds = Base64.getEncoder()

                                                        .encodeToString((basicAuthUser + ":" + basicAuthPass).getBytes("UTF-8"));

        Response response = service.path("mypath").request().accept("application/xml")

                                                     .header("Content-type", "application/xml")
                                                     .header("Authorization", "Basic " + base64Creds).post(Entity.xml(myRequestPojo));

       return response.readEntity(MyResponsePOJO.class);
      
    }



============== LOG response and request bodies in XML or JSON with the RequestResponseLoggingFilter =======

import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FilterOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.logging.Logger;

import javax.annotation.Priority;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.client.ClientRequestContext;
import javax.ws.rs.client.ClientRequestFilter;
import javax.ws.rs.client.ClientResponseContext;
import javax.ws.rs.client.ClientResponseFilter;
import javax.ws.rs.ext.Provider;
import javax.ws.rs.ext.WriterInterceptor;
import javax.ws.rs.ext.WriterInterceptorContext;

/**
 * @author tim 

 * 
 * Purpose is to log request and response payload as XML.
 */

@Provider
@Priority(Integer.MIN_VALUE)
public class RequestResponseLoggingFilter implements ClientRequestFilter, ClientResponseFilter, WriterInterceptor {

    private static final Logger LOG = Logger.getLogger(RequestResponseLoggingFilter.class.getName());

    private final int maximumSizeForEntity = 1024 * 8;

    private class StreamLogger extends FilterOutputStream {

        private final StringBuilder builder = new StringBuilder();
        private final ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();

        StreamLogger(OutputStream outputStream) {
            super(outputStream);
        }

        public StringBuilder writeEntity(Charset charset) {
            final byte[] pojo = byteArrayOutputStream.toByteArray();
            builder.append(new String(pojo, 0, pojo.length, charset));
            if (pojo.length > maximumSizeForEntity) {
                builder.append("...more...");
            }
            builder.append('\n');
            return builder;
        }

        @Override
        public void write(final int i) throws IOException {
            if (byteArrayOutputStream.size() <= maximumSizeForEntity) {
                byteArrayOutputStream.write(i);
            }
            out.write(i);
        }
    }

    @Override
    public void filter(ClientRequestContext requestContext) throws IOException {
        if (requestContext.hasEntity()) {
            final OutputStream stream = new StreamLogger(requestContext.getEntityStream());
            requestContext.setEntityStream(stream);
            requestContext.setProperty("EntityLoggingFilter.entityStream", stream);
        } else {
            // nop
        }
    }

    @Override
    public void filter(ClientRequestContext requestCtx, ClientResponseContext responseCtx) throws IOException {
        final StringBuilder stringBuilder = new StringBuilder();
        if (responseCtx.hasEntity()) {
            responseCtx.setEntityStream(logIncoming(stringBuilder, responseCtx.getEntityStream(), StandardCharsets.UTF_8));
            LOG.info(stringBuilder.toString());
        }

    }

    @Override
    public void aroundWriteTo(WriterInterceptorContext ctx) throws IOException, WebApplicationException {
        final StreamLogger stream = (StreamLogger) ctx.getProperty("EntityLoggingFilter.entityStream");
        ctx.proceed();
        if (stream != null) {
            LOG.info(stream.writeEntity(StandardCharsets.UTF_8).toString());
        } else {
            // nop
        }
    }

    private InputStream logIncoming(final StringBuilder b, InputStream stream, final Charset charset) throws IOException {
        if (!stream.markSupported()) {
            stream = new BufferedInputStream(stream);
        }
        stream.mark(maximumSizeForEntity + 1);
        final byte[] pojo = new byte[maximumSizeForEntity + 1];
        final int entitySize = stream.read(pojo);
        b.append(new String(pojo, 0, Math.min(entitySize, maximumSizeForEntity), charset));
        if (entitySize > maximumSizeForEntity) {
            b.append("...more...");
        } else {
            // nop
        }
        b.append('\n');
        stream.reset();
        return stream;
    }
}


================ DEPENDENCIES ================================

org="org.apache.logging.log4j" name="log4j" version = 2.5
org="org.glassfish.jersey" name="jersey" version =2.25.1
org="org.eclipse.persistence" name="eclipse-persistence" version = 2.6.0


<!-- required for Eclipse moxy, jaxb alternative) -->
org="javax.validation" name="validation-api" version = 1.1.0.Final





Freitag, 4. Mai 2018

Java UNIT Test Exception Handling with @Rule

A nice way to get rid of manual Exception handling in JUnit Tests is this:

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


 @Test
 public void testSomething() {


      // given
        thrownException.expect(MyExpectedException.class);
        thrownException.expectMessage("my expected msg");
        thrownException.reportMissingExceptionWithMessage("my custom msg");
 

      /*  possibly doing setup of mocks which throw the Exception... */

      // when / then
      testee.doSomething(); // throws the Exception...
 }

Donnerstag, 3. Mai 2018

Java Logging Log4j vs. SLF4J

Very good article which I recently found:
https://blog.frankel.ch/thoughts-on-java-logging-and-slf4j/https://blog.frankel.ch/thoughts-on-java-logging-and-slf4j/

Java Optional Example

Some people say that Optionals should only be used for API designs.

I think there is more to it and we can modernize our code. See this Nullpointer Exception. In this example we get rid of this:

//myList = null;
myList.add(myParam);


In favor of that:

Optional.ofNullable(myParam).ifPresent(myList::add);
//.of(myParam) would have thrown a Nullpointer if not present...

And for Exceptions, we get rid of this:

if (token == null) {
    throw new MyException("message");

}

In favor of that:


Optional.ofNullable(token).orElseThrow(() -> new MyException("message"));


Donnerstag, 19. April 2018

Remove ns2 in default namespace - JAXB, Entity XML Mapping

Just create a package-info.java file for your package in which you have your POJO:

@javax.xml.bind.annotation.XmlSchema(namespace = "http://myNameSpace", elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED)
package my.package;


The ns2 will be gone when you perform the usual Entity.xml(...)

Mittwoch, 18. April 2018

Generate JAXB Java Classes from XSD File

This is a fine one: if you only do have XML and nothing else, you can generate an XSD from the XML (here) and use the XSD to generate your Java POJOS.

I am currently forced to use windows, so I will use this example.

Download jaxb-ri-2.3.0 (Version may differ for you, what ever is the newest version).
Open CMD window and change to the directory  jaxb-ri-2.3.0\jaxb-ri\bin
Copy your XSD into the folder and type:
xjc.bat <yourfile.xsd> -d <yourDirectory>

And your POJOs will be generated, ready to use.

Dienstag, 27. März 2018

JAXB simplified JSON mapping + Rendering - How to parse Jaxb Response into POJO Java Class


How to parse Jaxb Response into POJO class:


Old:
//no POJO, but normal Response which still needs parsing…
Response response = service.request().accept(...).header(...)
                 .post(Entity.entity(myPojo, MediaType.APPLICATION_JSON_TYPE.withCharset("UTF-8")));

New:
// POJO, which can immediately be used…        
MyPOJOClass responsePojo = service.request().accept(...).header(...)
                 .post(Entity.json(myPojo), MyPOJOClass.class);


How to convert POJO to JAXB JSON Entity:


Old:
Entity.entity(myPojo, MediaType.APPLICATION_JSON_TYPE.withCharset("UTF-8"))

New:
Entity.json(myPojo)


 

How to print JSON request and response body in JAXB

Write a Filter for the Logging. Do not forget to annotate and register it:

import javax.ws.rs.client.Client;

client.register(new EntityLoggingFilter());


Filter Class:

import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FilterOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.logging.Logger;

import javax.annotation.Priority;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.client.ClientRequestContext;
import javax.ws.rs.client.ClientRequestFilter;
import javax.ws.rs.client.ClientResponseContext;
import javax.ws.rs.client.ClientResponseFilter;
import javax.ws.rs.ext.Provider;
import javax.ws.rs.ext.WriterInterceptor;
import javax.ws.rs.ext.WriterInterceptorContext;

@Priority(Integer.MIN_VALUE)
@Provider
public class EntityLoggingFilter implements ClientRequestFilter, ClientResponseFilter, WriterInterceptor {

    private static final Logger logger = Logger.getLogger(EntityLoggingFilter.class.getName());
    private static final String ENTITY_STREAM_PROPERTY = "EntityLoggingFilter.entityStream";
    private static final Charset DEFAULT_CHARSET = StandardCharsets.UTF_8;
    private final int maxEntitySize = 1024 * 8;

    private void log(StringBuilder sb) {
        logger.info(sb.toString());
    }

    private InputStream logInboundEntity(final StringBuilder b, InputStream stream, final Charset charset) throws IOException {
        if (!stream.markSupported()) {
            stream = new BufferedInputStream(stream);
        }
        stream.mark(maxEntitySize + 1);
        final byte[] entity = new byte[maxEntitySize + 1];
        final int entitySize = stream.read(entity);
        b.append(new String(entity, 0, Math.min(entitySize, maxEntitySize), charset));
        if (entitySize > maxEntitySize) {
            b.append("...more...");
        }
        b.append('\n');
        stream.reset();
        return stream;
    }

    @Override
    public void filter(ClientRequestContext requestContext) throws IOException {
        if (requestContext.hasEntity()) {
            final OutputStream stream = new LoggingStream(requestContext.getEntityStream());
            requestContext.setEntityStream(stream);
            requestContext.setProperty(ENTITY_STREAM_PROPERTY, stream);
        }
    }

    @Override
    public void filter(ClientRequestContext requestContext, ClientResponseContext responseContext) throws IOException {
        final StringBuilder sb = new StringBuilder();
        if (responseContext.hasEntity()) {
            responseContext.setEntityStream(logInboundEntity(sb, responseContext.getEntityStream(), DEFAULT_CHARSET));
            log(sb);
        }

    }

    @Override
    public void aroundWriteTo(WriterInterceptorContext context) throws IOException, WebApplicationException {
        final LoggingStream stream = (LoggingStream) context.getProperty(ENTITY_STREAM_PROPERTY);
        context.proceed();
        if (stream != null) {
            log(stream.getStringBuilder(DEFAULT_CHARSET));
        }
    }

    private class LoggingStream extends FilterOutputStream {

        private final StringBuilder sb = new StringBuilder();
        private final ByteArrayOutputStream baos = new ByteArrayOutputStream();

        LoggingStream(OutputStream out) {
            super(out);
        }

        StringBuilder getStringBuilder(Charset charset) {
            // write entity to the builder
            final byte[] entity = baos.toByteArray();

            sb.append(new String(entity, 0, entity.length, charset));
            if (entity.length > maxEntitySize) {
                sb.append("...more...");
            }
            sb.append('\n');

            return sb;
        }

        @Override
        public void write(final int i) throws IOException {
            if (baos.size() <= maxEntitySize) {
                baos.write(i);
            }
            out.write(i);
        }
    }
}

Mittwoch, 21. März 2018

How to map a java.util.Date to a specific JSON java.lang.String - Date Serialization with Jackson 2.8.4

I do prefer Jackson for serializing and deserializing from and to JSON.

For Date to String conversion you do only need one simple annotation:


import com.fasterxml.jackson.annotation.JsonFormat;

// "2018-03-02T12:00:00";
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyy-MM-dd'T'HH:mm:ss")
public Date TimeStamp;

NEW BLOG! http://cleancode.consulting/

Dear Reader, This Blog is closed and remains as an archive. Please find our new Blog at  http://cleancode.consulting/