DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Newsletter
Log In / Join
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Related

  • Prototype for a Java Database Application With REST and Security
  • Introducing Graph Concepts in Java With Eclipse JNoSQL
  • Jakarta NoSQL 1.0: A Way To Bring Java and NoSQL Together
  • Handling Embedded Data in NoSQL With Java

Trending

  • Kill the Worker, Keep the Research: Build a Recoverable LangGraph Agent on Temporal
  • Building a Practical Cloud-Native Golden Path: A Guide to Kubernetes-Based Service Delivery, Self-Service, and Developer-Friendly Defaults
  • Going All In On the JVM 25 Virtual Threads
  • AI-Era Cybersecurity, Part 1: Mapping Glasswing, Daybreak, Lightwell and the Tools Racing to Find and Fix Bugs

Draft This article hasn't been published, so readers can't see it.

In moderation This article is waiting for review, so readers can't see it yet.

Deleted This article has been deleted, so readers can't see it.

  1. DZone
  2. Data Engineering
  3. Databases
  4. Efficiently Producing and Consuming CSV in Java Using HTTP-RPC

Efficiently Producing and Consuming CSV in Java Using HTTP-RPC

Want to learn how to produce and consume a CSV in Java? Check out this tutorial on producing CSVs, using HTTP-RPC.

By 
Greg Brown
·
Aug. 14, 18 · Tutorial
Post on X (opens in a new tab) Share on LinkedIn (opens in a new tab)
14.5K Views

Join the DZone community Save articles, join the discussion, and download Refcards and Trend Reports with a free account.

Join for free Already a member? Log in

In a previous article, I discussed how the open-source HTTP-RPC framework can be used to efficiently transform JDBC query results into JSON. However, while JSON is an extremely common and well-supported data format, it may, in some cases, be preferable to return a CSV document instead. Because field keys are specified only at the beginning of a CSV document rather than being duplicated for every record, CSV generally requires less bandwidth than JSON. Additionally, consumers can begin processing CSV as soon as the first record arrives, rather than waiting for the entire document to download.

The previous article demonstrated how HTTP-RPC's ResultSetAdapter and JSONEncoder classes could be used to easily generate a JSON response from a SQL query on this table, taken from the MySQL sample database:

CREATE TABLE pet (
    name VARCHAR(20),
    owner VARCHAR(20),
    species VARCHAR(20), 
    sex CHAR(1), 
    birth DATE, 
    death DATE
);


The following service method returns the same results encoded as CSV. The only difference in this version is the use of HTTP-RPC's CSVEncoder class instead of JSONEncoder:

@RequestMethod("GET")
public void getPets(String owner) throws SQLException, IOException {
    try (Connection connection = DriverManager.getConnection(DB_URL)) {
        Parameters parameters = Parameters.parse("SELECT name, species, sex, birth FROM pet WHERE owner = :owner");

        parameters.put("owner", owner);

        try (PreparedStatement statement = connection.prepareStatement(parameters.getSQL())) {
            parameters.apply(statement);

            try (ResultSet resultSet = statement.executeQuery()) {
                CSVEncoder csvEncoder = new CSVEncoder();

                csvEncoder.writeValue(new ResultSetAdapter(resultSet), getResponse().getOutputStream());
            }
        }
    } finally {
        getResponse().flushBuffer();
    }
}


The response might look something like this, where each record in the document represents a row from the result set (date values are represented using epoch time):

"name","species","sex","birth"
"Claws","cat","m",763880400000
"Chirpy","bird","f",905486400000
"Whistler","bird",,881643600000


Consuming a CSV Response

On the other end, the HTTP-RPC's CSVDecoder class can be used to efficiently process the contents of a CSV document. Rather than reading the entire payload into memory and returning the data as a random-access list of map values, CSVDecoder returns a cursor over the records in the document. This allows a client to read records as they are being produced, reducing memory consumption and improving throughput.

For example, the following client code could be used to consume the response generated by the web service:

WebServiceProxy webServiceProxy = new WebServiceProxy("GET", new URL("http://localhost:8080/httprpc-test/pets"));

webServiceProxy.getArguments().put("owner", "Gwen");
webServiceProxy.getArguments().put("format", "csv");

webServiceProxy.invoke((inputStream, contentType) -> {
    CSVDecoder csvDecoder = new CSVDecoder();

    CSVDecoder.Cursor pets = csvDecoder.readValues(inputStream);

    for (Map<String, String> pet : pets) {
        System.out.println(String.format("%s is a %s", pet.get("name"), pet.get("species")));
    }

    return null;
});


This code produces the following output:

Claws is a cat
Chirpy is a bird
Whistler is a bird


Additionally, the adapt() method of the CSVDecoder.Cursor class can be used to facilitate typed iteration of CSV data. This method produces an Iterable sequence of values of a given type representing the rows in the document. The returned adapter uses dynamic proxy invocation to map properties declared by the interface to map values in the cursor. A single proxy instance is used for all rows to minimize heap allocation.

For example, the following interface might be used to model the pet records shown above:

public interface Pet {
    public String getName();
    public String getOwner();
    public String getSpecies();
    public String getSex();
    public Date getBirth();
}


This code uses adapt() to create an iterable sequence of Pet values from the CSV response:

CSVDecoder csvDecoder = new CSVDecoder();

CSVDecoder.Cursor pets = csvDecoder.readValues(inputStream);

for (Pet pet : pets.adapt(Pet.class)) {
    System.out.println(String.format("%s is a %s", pet.getName(), pet.getSpecies()));
}


The output is identical to the previous example; however, in this case, the fields of each record are retrieved in a type-safe manner (a feature whose value becomes much more obvious when handling CSV documents containing numeric or boolean values).

Final Thoughts

This article provided an example of how HTTP-RPC's CSVEncoder and CSVDecoder classes can be used to efficiently stream and process JDBC query results as CSV. For more information, see the project README.

CSV Database Java (programming language)

Opinions expressed by DZone contributors are their own.

Related

  • Prototype for a Java Database Application With REST and Security
  • Introducing Graph Concepts in Java With Eclipse JNoSQL
  • Jakarta NoSQL 1.0: A Way To Bring Java and NoSQL Together
  • Handling Embedded Data in NoSQL With Java

Partner Resources

×

Comments

Loading comments

The comments didn't load

Please try again in a moment.

Likes

Loading

The next likes didn't load. Please try again.

The likes didn't load

Please try again in a moment.

See who liked this

Log in or join DZone for free to see who liked this article.

Log in Join for free
  • RSS
  • X
  • Facebook

ABOUT US

  • About DZone
  • Support and feedback
  • Community research

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 215
  • Nashville, TN 37211
  • [email protected]

Let's be friends:

  • RSS
  • X
  • Facebook