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;

Dienstag, 20. März 2018

On Testing, Databases and Testdata - TDD Success Story

I was on-site at a large software company, reknown and with a ton of reputation. They are doing things with your money, you know. So they have to be secure.

Now, there was a habit there, to use live data for testing. Something which is sometimes done.
Anyway, they claimed that, because it was live-data they were testing with, it was a very good thing to use live-data and because every second day there would be an update of data from the live database to the test database, everything would be up-to-date. Good idea. You might think.

And then, after three months of development, it happened.
A customer dared - yes I use the word DARED by intention to point out the irony - he dared to use the core feature of the the software, which was to create or change price models.

There were not ten price models. Not a hundred. There were a thousand price models. Something in that range. And the customer decided to change about 90% of them. Yes.

The very next morning, the data had already been cloned into the dev database.
Because the administrators are unfortunately overwhelmed by the amounts of data they are dealing with, they do not manage to perform a rollback.

Prior to the next release, which was planned for the next day, they were admittedly unable to do a rollback. The testers, experienced guys, external employees like I, said in the emergency meeting that the software cannot be reliably tested.

That was it. To cancel the release would have meant breeching contractual agreements with at least two of the largest customers. What could we do?

2 months before I had a personal interview with the Head of Development, a good guy with profound knowledge who is suffering from a constant lack of resources (by saying resources the company means actual human employees, just to make it clear). He instructed me NOT to write too many UNIT tests. Because this would only slow down the development which is under constant pressure from the business side because it performs at a pace being considered too slow for the mega advanced Management. So omitting the Tests would speed it up. So he said.

Needless to say that I ignored it. I wrote tests for the most important functions, basically a lot of math for financial calculation. UNIT based, independent from the database. Maybe the Head of Dev would have cancelled our contract if he would have known at the time. But I knew that arguing would not make a difference for a person being under such pressure. The team had tried before and been ignored.

Now, when we had this emergency meeting, I said: "We can do the release."
Eyes stared at me with the expression of a panicking animal. "What?"
I said: "We can because I have UNIT tests for all your business functions."
"What?"
"Yes. Calculation is correct. Let's do the release."

The release was done and everything went pretty smoothly.

A few days after, the Head of Dev approached me by saying that doing UNIT Tests for the business critical parts of the software would be a very good thing and encouraged the whole team to establish this technique from now on. Really true.

I even managed to introduce them to Pair Programming, my favorite XP technique besides TDD, but that is another story, eh, post.

All the best,
Tim












Freitag, 16. März 2018

Online Tutorials, Generation Tools for Basic Auth + JSON

Hi there,

I found a nice and simple authentication header generator for Basic Authentication:
https://www.blitter.se/utils/basic-authentication-header-generator/

Probably the best JSON formatter online (pretty-print), nice for analysis:
https://jsonformatter.curiousconcept.com/

Both useful for doing ad-hoc requests, maybe with
Advanced Rest Client: https://chrome.google.com/webstore/detail/advanced-rest-client/hgmloofddffdnphfgcellkdfbfbjeloo

Last but not least a nice collection of mini tutorials. Focused on practicality:
http://www.mkyong.com/all-tutorials-on-mkyong-com/

Best,
Tim 

Freitag, 9. März 2018

Harder IT Consulting - JAVA für Hamburg. Ab Juni 2018!

Liebe Leser,

ab Juni 2018 geht es los. Als IT Consultant bin ich für Rollen in den Bereichen Architektur, Design und Coaching buchbar.

Harder IT Consulting ist meine dritte Firma (die erste habe ich verkauft, die zweite ist eine reine Produktlinie, die dritte ist Harder IT Consulting).

Dort, wo Kompetenzen für Java oder komplexe Software Architekturen und vertrackte Probleme in diesen gelöst werden müssen, sieht man mich häufig.


Der Feuerwehrmann sucht immer den Brandherd.

  • Haben Sie zuwenig Entwickler?
  • Sind Ihre Teams überlastet?
  • Haben Sie Probleme mit einer vertrackten Softwarelandschaft?
  • Brauchen Sie Software-Kompetenz mit Erfahrung?

Zufriedene Kunden sind unter anderem:
Kühne + Nagel, BMW, U.S. Navy, EOS, Universal, Vodafone, O2...

Schreiben Sie, rufen Sie an, ich freue mich.

Freundliche Grüße aus Hamburg Bergedorf,

 Tim Harder
- Inhaber -

HARDER IT CONSULTING
Tim Harder - Inhaber

Fanny-Lewald-Ring 128
21035 Hamburg

Mobil: +49 172 4289053
Mail: tim@harder-it-consulting.de   -   Web: www.harder-it-consulting.de

XING LinkedIn

Blog: GOOD NEWS FROM THE IT CROWDhttps://harderconsulting.blogspot.de/





<a href="https://www.freelancermap.de/freelancer-verzeichnis/profile/entwicklung/142866-profil-tim-harder-harder-it-consulting-inhaber-consultant-entwickler-architekt-buchbar-ab-juni-2018-aus-hamburg.html" target="_blank" title="Profil von Tim Harder auf www.freelancermap.de"><img src="https://www.freelancermap.de/images/widgets/button/findenSieMich.png"></a>

DOCKER - No Space Left on Device // How to clean Docker on Linux

Sometimes Docker will simply claim to much space. Time for a clean up ;) docker system prune -a -f