Please, Java. Do Finally Support Multiline String Literals

I understand the idea of Java-the-language being rather hard to maintain in a backwards-compatible way. I understand the idea of JDK API, such as the collections, to be rather tough not to break. Yes.

I don’t understand why Java still doesn’t have multiline string literals.

How often do you write JDBC code (or whatever other external language or markup, say, JSON or XML you want to embed in Java) like this?

try (PreparedStatement s = connection.prepareStatement(
    "SELECT * "
  + "FROM my_table "
  + "WHERE a = b "
)) {

What’s the issue?

  • Syntax correctness, i.e. don’t forget to add a whitespace at the end of each line
  • Style in host language vs style in external language, sure the above code looks “nicely” formatted in Java, but it’s not formatted for the consuming server side
  • SQL injection, didn’t we teach our juniors not to perform this kind of string concatenation in SQL, to prevent SQL injection? Sure, the above is still safe, but what keeps a less experienced maintainer from embedding, accidentally, user input?

Today, I was working with some code written in Xtend, a very interesting language that compiles into Java source code. Xtend is exceptionally useful for templating (e.g. for generating jOOQ’s Record1Record22 API). I noticed another very nice feature of multi line strings:

The lack of need for escaping!

Multi line strings in Xtend are terminated by triple-apostrophes. E.g.

// Xtend
val regex = '''import java\.lang\.AutoCloseable;'''

Yes, the above is a valid Java regular expression. I’m escaping the dots when matching imports of the AutoCloseable type. I don’t have to do this tedious double-escaping that I have to do in ordinary strings to tell the Java compiler that the backslash is really a backslash, not Java escaping of the following character:

// Java
String regex = "import java\\.lang\\.AutoCloseable;";

So… Translated to our original SQL example, I would really like to write this, instead:

try (PreparedStatement s = connection.prepareStatement(
    '''SELECT *
       FROM my_table
       WHERE a = b'''
)) {

With a big nice-to-have plus: String interpolation (even PHP has it)!

String tableName = "my_table";
int b = 1;
try (PreparedStatement s = connection.prepareStatement(
    '''SELECT *
       FROM ${tableName}
       WHERE a = ${b}'''
)) {

Small but very effective improvement

This would be a very small (in terms of language complexity budget: Just one new token) but very effective improvement for all of us out there who are embedding an external language (SQL, XML, XPath, Regex, you name it) in Java. We do that a lot. And we hate it.

It doesn’t have to be as powerful as Xtend’s multiline string literals (which really rock with their whitespace management for formatting, and templating expressions). But it would be a start.

Please, make this a New Year’s resolution!🙂

25 thoughts on “Please, Java. Do Finally Support Multiline String Literals

  1. I am not against the multi-line string feature, but you don’t have to wait for anything – just use a proper IDE🙂

    That will solve at least some of your issues:
    – syntax highlighting and correctness (table and column names included!!)
    – some kind of “edit fragment” feature should do the escaping automatically (in regexes as well as in sql)

    I am not sure what you mean by the style (2nd bullet point), and how it would change with string interpolation).

    I wouldn’t worry too much about the SQL injection – as you are already using prepared statement anyone with a bit of sense will use that properly. And checkstyle/findbugs to the rescue if they don’t.

    I am sure you know what IDE I am talking about🙂.

    • Indeed, that “proper IDE” does help a bit. But I’m talking about the possibility of implementing a complex query in SQL Developer and then just copy-pasting it into my Java program. Or XML. Or JSON. Or properties. Or any other external DSL that I want to inline with Java code.

      And: I most certainly don’t want to escape anything, just because I’m putting it in a Java string that reserves the quote and backslash characters!

  2. I’m personally a fan of C# Syntax.

    @”Multi-line string with no need for escaping things here”

    ‘Regular string where you need to escape here”

    String interpolation is nice though – a bit nicer than the {0} syntax of String.Format.

  3. You realize your hypothetical multi-line string with interpolation Java example is _exactly_ the kind of string concatenation you should not do because injection?

    • How else would you dynamically insert a table in your SQL string?

      Granted, the multiline string literal version is just as good as the alternative concatenated version. But without concatenation, I claim there would be less accidents.

      • “How else would you dynamically insert a table in your SQL string?”

        … with JPA and Criteria API. But you have to desing carefully the DB schema.

        • You’re on the jOOQ blog. jOOQ got embedding arbitrary expressions (such as column, table, schema, catalog references) right as well, probably much more thoroughly than Criteria API.

          But we’re talking about embedded native SQL here. At some point, even jOOQ can’t model a complex SQL statement any longer, in case of which you will inevitably need to resort to strings.

  4. Nice point Lukas, indeed idea of three quotes make a lot more sense than using + for concatenation. I have myself forgotten to add whitespace so many times🙂

    • That’s an option, of course. But I’m not so sure if these approaches scale well. Somehow, there hasn’t been any popular Java code preprocessor in the last 20 years. Even SQLJ is pretty dead.

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s