Tuesday, October 15, 2019

Spring MVC - HTTP message converter

Quite often you need to provide users with the same data, but in different forms, like JSON, PDF, XLS, etc. If your application is Spring Framework based, this task can be achieved using HTTP message converters.

HTTP message converters are applied when HTTP request (or its parts) needs to be converted into type required for handler method argument (see: Handler methods - method arguments), or when value returned by handler method needs to be converted somehow to create HTTP response (see: Handler methods - Return values).

Spring Framework provides you with a set of predefined HTTP message converters, for ex. for byte arrays, JSON, etc. - This set can be modified or extended to your needs.
 
In this post we will focus on converting value returned from handler method into desired form, using example provided by me (see below for the link to the source code repository).

 Suppose that we have a controller returning some Team data, like this (yes, I know, I've ignored team Id)
@RestController
public class TeamDetailsController {

    @GetMapping("/teams/{teamId}/")
    public Team read() {
        final Set<TeamMember> members = new LinkedHashSet<>();
        members.add(new TeamMember("Albert Einstein", LocalDate.of(1879, 3, 14)));
        members.add(new TeamMember("Benjamin Franklin", LocalDate.of(1706, 1, 17)));
        members.add(new TeamMember("Isaac Newton", LocalDate.of(1643, 1, 4)));
        return new Team(members);
    }

}
In our example, handler method response will be, by default, converted into JSON:
{
  "members": [
    {
      "dateOfBirth": "1879-03-14",
      "name": "Albert Einstein"    },
    {
      "dateOfBirth": "1706-01-17",
      "name": "Benjamin Franklin"    },
    {
      "dateOfBirth": "1643-01-04",
      "name": "Isaac Newton"    }
  ]
}
If we would like to convert the data returned by the handler into XLS file, we can simply define a bean being HTTP message converter implementation, which will be activated by the HTTP Accept header:
@Service
public class TeamToXlsConverter extends AbstractHttpMessageConverter<Team> {

    private static final MediaType EXCEL_TYPE = MediaType.valueOf("application/vnd.ms-excel");

    TeamToXlsConverter() {
        super(EXCEL_TYPE);
    }

    @Override
    protected Team readInternal(final Class<? extends Team> clazz, final HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException {
        return null;
    }

    @Override
    protected boolean supports(final Class<?> clazz) {
        return (Team.class == clazz);
    }

    @Override
    protected void writeInternal(final Team team, final HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException {
        try (final Workbook workbook = new HSSFWorkbook()) {
            final Sheet sheet = workbook.createSheet();
            int rowNo = 0;
            for (final TeamMember member : team.getMembers()) {
                final Row row = sheet.createRow(rowNo++);
                row.createCell(0)
                   .setCellValue(member.getName());
            }
            workbook.write(outputMessage.getBody());
        }
    }

}
You have to keep in mind that in our example, defined HTTP message converter will be applied always when the handler method returns value of type Team (see supports method), and HTTP Accept header matches "application/vnd.ms-excel". In this case, XLS file generated by the HTTP message converter is returned instead of JSON representation of Team.

Few links for the dessert:

Follow-ups:


This article has been republished on DZone's Java Zone (10/19/2019) and on Java Code Geeks (10/21/2019).

Saturday, August 3, 2019

JDBC - Emulating a sequence

Probably each of us encountered this problem at least once in the programmer's life - how to emulate a database sequence? Below you may find my variation of this problem's solution.

Suppose that we have an interface defining the desired API for returning a sequence of integer numbers:
public interface Sequences {

    int nextValue(String sequenceName) throws SQLException;

}
and the implementation of this API in the following form:
class SequencesService implements Sequences {

    private static final String SQL_QUERY =
        "SELECT SEQ_NAME, SEQ_VALUE FROM SEQUENCE WHERE SEQ_NAME = ? FOR UPDATE";

    private final DataSource dataSource;

    SequencesService(final DataSource dataSource) {
        this.dataSource = dataSource;
    }

    @Override
    public int nextValue(final String sequenceName) throws SQLException {
        final long threadId = Thread.currentThread().getId();

        try (final Connection connection = dataSource.getConnection()) {
            connection.setAutoCommit(false);
            try (final PreparedStatement statement =
                     connection.prepareStatement(
                         SQL_QUERY, TYPE_SCROLL_SENSITIVE, CONCUR_UPDATABLE)) {
                statement.setString(1, sequenceName);
                try (final ResultSet resultSet = statement.executeQuery()) {
                    System.out.println(
                        String.format("[%d] - select for update", threadId));
                    int nextValue = 1;
                    if (resultSet.next()) {
                        nextValue = 1 + resultSet.getInt(2);
                        resultSet.updateInt(2, nextValue);
                        resultSet.updateRow();
                    } else {
                        resultSet.moveToInsertRow();
                        resultSet.updateString(1, sequenceName);
                        resultSet.updateInt(2, nextValue);
                        resultSet.insertRow();
                    }
                    System.out.println(
                        String.format("[%d] - next val: %d", threadId, nextValue));
                    return nextValue;
                }
            } finally {
                System.out.println(String.format("[%d] - commit", threadId));
                connection.commit();
            }
        }
    }

}
You have to forgive me two things :) - the println usage, which I added for generating some visual feedback ;) and a lack of detailed explanation how this solution works ;) I'll just mention that the clue is the way prepared statement is created, and the result set handling: updateRow / moveToInsertRow / insertRow usage ;) (see the links at the bottom of this post for the details).

I wrote simple test case to observe and verify this code, something like:
@Autowired
private Sequences sequences;

private Callable<Integer> callable() {
    return () -> {
        System.out.println(String.format("[%d] - starting", Thread.currentThread().getId()));
        return sequences.nextValue("My Sequence");
    };
}

@Test
public void test() throws Exception {
    final ExecutorService executor = Executors.newFixedThreadPool(3);
    final CompletionService<Integer> completion = new ExecutorCompletionService<>(executor);

    for (int i = 0; i < 3; i++) {
        completion.submit(callable());
    }
    
    for (int completed = 1; completed <= 3; completed++) {
        final Future<Integer> result = completion.take();
        System.out.println(String.format("Result %d - %d", completed, result.get()));
        assertEquals(Integer.valueOf(completed), result.get());
    }
}
When run, the above code, the output will be something like this (threads' IDs in the brackets):
[16] - starting
[18] - starting
[17] - starting
[17] - select for update
[17] - next val: 1
[17] - commit
[18] - select for update
Result 1 - 1
[18] - next val: 2
[18] - commit
[16] - select for update
[16] - next val: 3
[16] - commit
Result 2 - 2
Result 3 - 3

This code is just for demonstration purposes :) - if you want to do something similar in your project, it's probable that you will rather use for ex. Spring Framework's @Transactional annotation, instead of manual transactions handling, or even JPA delegating this work to JDBC. For example in Hibernate you may do it somehow like this:
import org.hibernate.Session;
...

entityManager.unwrap(Session.class)
                      .doReturningWork(connection -> { ... code derived from my example ... });

Few links for the dessert:
... and I almost forgot ;) - GitHub repository holding all my code expriments for this post


Follow-ups:

 

This article has been republished on DZone's Database Zone (08/21/2019).

Sunday, June 15, 2014

Serialization Proxy Pattern example

There are books, which change your life immensely. One of such books is "Effective Java" by Joshua Bloch. Below you may find small experiment, which was inspired by Chapter 11 of this book - "Serialization".

Suppose that we have a class designed for inheritance, which is not Serializable itself, and has no parameterless constructor, like in this example:
public class CumbersomePoint {

    private String name;

    private double x;

    private double y;

    protected CumbersomePoint(double x, double y, String name) {
        this.x = x;
        this.y = y;
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public double getX() {
        return x;
    }

    public double getY() {
        return y;
    }

    ...
}
Now when we extend this class, for example in following way:
public class ConvenientPoint extends CumbersomePoint implements Serializable {

    public ConvenientPoint(double x, double y, String name) {
        super(x, y, name);
    }

    ...
}
and try to serialize and then deserialize any of ConvenientPoint instances, we'll quickly encounter beautiful InvalidClassException, complaining that there is no valid constructor. Situation looks kinda hopeless, until you apply technique known as Serialization Proxy Pattern.

We will start by adding to the ConvenientPoint class following inner class:
private static class SerializationProxy implements Serializable {

        private String name;

        private double x;

        private double y;

        public SerializationProxy(ConvenientPoint point) {
            this.name = point.getName();
            this.x = point.getX();
            this.y = point.getY();
        }

        private Object readResolve() {
            return new ConvenientPoint(x, y, name);
        }

    }
The SerializationProxy class will represent the logical state of enclosing class instance. We will have to add also following method to ConvenientPoint class:
    private Object writeReplace() {
        return new SerializationProxy(this);
    }

Now when the ConvenientPoint instance will be serialized, it will nominate its replacement, thanks to writeReplace method - SerializationProxy instance will be serialized instead of ConvenientPoint.

From the other side, when SerializationProxy will be deserialized, readResolve method usage will nominate its replacement, being ConvenientPoint instance.

As you see, we've made ConvenientPoint serializable, regardless of missing parameterless constructor of non-serializable parent class.

One more remark, at the end of this post - if you want to protect against breaking class invariants, enforced by the constructor, you may add following method to class using Serialization Proxy Pattern (ConvenientPoint in our example): 
    private void readObject(ObjectInputStream stream) throws InvalidObjectException {
        throw new InvalidObjectException("Use Serialization Proxy instead.");
    }
It will prevent deserialization of the enclosing class.

Sunday, May 4, 2014

@OneToOne with shared primary key, revisited :)

Long time ago, I wrote a post @OneToOne with shared primary key. Today I would like to return to this problem, with solution based on @MapsId annotation introduced in JPA 2.0

Again we have two entities: Primus and Secundus. Both entities have primary key using Long Java type. They are related 1-1, and Secundus should use the same primary key as Primus.
3 Years after my initial post they will look slightly different ;)
@Entity
@Table(name = "PRIMUS")
public class Primus {

    public static Primus newInstance() {
        Primus primus = new Primus();
        primus.secundus = new Secundus(primus);
        return primus;
    }

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @OneToOne(cascade = CascadeType.ALL, mappedBy = "primus")
    private Secundus secundus;

    Primus() {
        super();
    }
    ...

}
Not much changed here, ;). Really important changes were made on the Secundus:
@Entity
@Table(name = "SECUNDUS")
public class Secundus {

    @Id
    private Long id;

    @JoinColumn(name = "ID")
    @OneToOne
    @MapsId
    private Primus primus;

    Secundus() {
        super();
    }

    public Secundus(Primus primus) {
        this();
        this.primus = primus;
    }
As you see, the @PrimaryKeyJoinColumn annotation is replaced with two annotations: @MapsId, which defines that Secundus identifier will be determined by Primus identifier, and @JoinColumn, specifying which column in SECUNDUS table will be used for joining. 

Nothing more is needed :) - JPA Provider should automatically ask Primus for its identifier, when persisting Secundus, as long as you take care of correct entities correlation, like in newInstance method of Primus.

Long live JPA 2.0+ ;) :) 

Saturday, May 11, 2013

JPA - Querydsl Projections

In my last post: JPA - Basic Projections - I've mentioned about two basic possibilities of building JPA Projections. This post brings you more examples, this time based on Querydsl framework. Note, that I'm referring Querydsl version 3.1.1 here.

Reinvented constructor expressions


Take a look at the following code:

The above Querydsl construction means: create new JPQL query [1] [2], using employee as the data source, order the data using employee name [3], and return the list of EmployeeNameProjection, built using the 2-arg constructor called with employee ID and name [4].  This is very similar to the constructor expressions example from my previous post (JPA - Basic Projections), and leads to the following SQL query:

select EMPLOYEE_ID, EMPLOYEE_NAME from EMPLOYEE order by EMPLOYEE_NAME asc

As you see above, the main advantage comparing to the JPA constructor expressions is using Java class, instead of its name hard-coded in JPQL query.

Even more reinvented constructor expressions


Querydsl documentation [4] describes another way of using constructor expressions, requiring @QueryProjection annotation and Query Type [1] usage for projection, see example below. Let's start with the projection class modification - note that I added @QueryProjection annotation on the class constructor.

Now we may use modified projection class (and corresponding Query Type [1] ) in following way:

Which leads to SQL query:

select EMPLOYEE_ID, EMPLOYEE_NAME from EMPLOYEE order by EMPLOYEE_NAME asc

In fact, when you take a closer look at the Query Type [1] generated for EmployeeNameProjection (QEmployeeNameProjection), you will see it is some kind of "shortcut" for creating constructor expression the way described in first section of this post.

Mapping projection


Querydsl provides another way of building projections, using factories based on MappingProjection.


The above class is a simple factory creating EmployeeNameProjection instances using employee ID and name. Note that the factory constructor defines which employee properties will be used for building the projection, and map method defines how the instances will be created.

Below you may find an example of using the factory:

As you see, the one and only difference here, comparing to constructor expression examples, is the list method call.

Above example leads again to the very simple SQL query:

select EMPLOYEE_ID, EMPLOYEE_NAME from EMPLOYEE order by EMPLOYEE_NAME asc

Building projections this way is much more powerful, and doesn't require existence of n-arg projection constructor.

QBean based projection (JavaBeans strike again)


There is at least one more possibility of creating projection with Querydsl - QBean based - in this case we build the result list using:

... .list(Projections.bean(EmployeeNameProjection.class, employee.employeeId, employee.name))

This way requires EmployeeNameProjection class to follow JavaBean conventions, which is not always desired in application. Use it if you want, but you have been warned ;)

Few links for the dessert

  1. Using Query Types
  2. Querying
  3. Ordering
  4. Constructor projections


Follow-ups:


This article has been republished on Java Code Geeks (05/14/2013), and on Dzone's Javalobby (05/15/2013).