9

I'm running a Java EE application which uses Hibernate 5.2.10.Final with an Apache Derby storage backend on Payara 4.1.1.172. I'm seeing error messages like

Caused by: java.sql.SQLDataException: A truncation error was encountered trying to shrink VARCHAR () FOR BIT DATA '(Binärer Datenwert wird nicht angezeigt)' to length 255.

which indicates that either Hibernate or Derby or both are not using english error messages in all parts of the message.

I tried to

  • add a

    static {
        System.setProperty("user.language", "en");
        System.setProperty("user.region", "en_US");
    }
    

    to a class, but I don't seem to find a deterministic way to get this loaded before any exception occurs and I'd rather like to keep the setting out of the code. The same thus applies to Locale.setDefault.

  • specify -Duser.language=en in the Payara JVM options of server-config as describe at How to enable assertion for a Java EE project in NetBeans?

I see that the beginning of the exception message is in English. I want the complete message to be in English including all possible parts. I'm not interesting in solving the exception, it's an example. I'm not looking for a translation of the German part of the message.

The non-English message part is most likely caused by the German Ubuntu 18.04 the server is started on. Changing the system locale of the OS or a container the server could be wrapped into is a workaround, but not a solution.

A SSCCE can be found at https://gitlab.com/krichter/derby-embedded-data-source-locale-j4ee and example output of the CI at https://gitlab.com/krichter/derby-embedded-data-source-locale-j4ee/-/jobs/83525395. The SSCCE only contains boilerplate around the server start and a simple invalid native query causing a german error message, not more information than provided in the question.

Please verify answers with the SSCCE if possible.

My motivation is to have English exception messages in order to make finding solution through search engines easier during development without tampering with the system language.

Kalle Richter
  • 8,008
  • 26
  • 77
  • 177
  • That error message **is** in English. The part of the message that is between the single quotes is your own data (the data that could not be shrunk to length 255) – Bryan Pendleton Jun 02 '17 at 17:29
  • I would say that the message comes from Derby - the data is binary and therefore Derby cannot display them and prints a german message "binary data isn't displayed". But I don't know how to change this to English. – OndroMih Jun 06 '17 at 23:29
  • It's a Derby error message. Check out [line 6006](https://github.com/apache/derby/blob/trunk/java/org.apache.derby.engine/org/apache/derby/loc/messages_de_DE.properties). – Paul Hicks Jul 17 '18 at 21:13
  • Instead of `-Duser.locale=en` try `-Duser.language=en` – Loris Securo Jul 17 '18 at 21:38
  • 1
    I've gone through the source and I can't see any way to change the locale used for exception messages to be anything other than the database locale. The database locale is stored in a context, and theoretically it [should be possible to have a different context for exceptions](https://github.com/apache/derby/blob/0b09cc33dfe8c60a63af8d9ddbe496b9ff014a55/java/org.apache.derby.engine/org/apache/derby/impl/db/BasicDatabase.java#L560), but I can't see where that would be configured. – Paul Hicks Jul 17 '18 at 21:39
  • @LorisSecuro Thanks for you input, but [that doesn't help](https://gitlab.com/krichter/derby-embedded-data-source-locale/-/jobs/82458059). – Kalle Richter Jul 17 '18 at 21:44
  • @PaulHicks Thanks for your research. That's a pity. I added an explanation of my motivation to my question which imo makes it a desirable feature to be able to get exception messages in a different language than the one associated with the database locale. – Kalle Richter Jul 17 '18 at 21:47
  • You could "hack" it by deleting (or moving..) the error messages jar (yes, it seems to be a separate jar, see [the getting started docs](https://builds.apache.org/job/Derby-docs/lastSuccessfulBuild/artifact/trunk/out/getstart/index.html)). If you get rid of `derbyLocale_de_DE.jar` it should fall back to English. – Paul Hicks Jul 17 '18 at 22:00
  • Looking at the log, after the call to `startNetworkServer` the log says `Argument -Duser.language=en ist unbekannt.` (which should mean "argument is unknown"), so it seems that those parameters are not correctly reaching the JVM. – Loris Securo Jul 17 '18 at 22:06
  • Error message is present in Derby as said by @PaulHicks but that does not mean the problem is on Derby, the problem I would say is why Derby is picking the properties file from german instead of english, well, for internationalization we know we have to retrieve resource files with ResourceBundle.getBundle("", Locale), knowing that, try to trace the source code, I will help you with key points: 1. https://github.com/apache/derby/search?utf8=%E2%9C%93&q=ResourceBundle.getBundle&type= 2. https://github.com/apache/derby/search?q=getBundle%28&unscoped_q=getBundle%28 – Melardev Jul 22 '18 at 13:52
  • [Continued] By reading the source code you can see it is related to the Locale the application retrieves, so there is a this link https://stackoverflow.com/a/8809162/6393636 which you can read to learn about the means to change the locale for the JVM, the summary: change user.language, user.country, and user.variant with -D, example java -jar app.jar -Duser.language=en-EN – Melardev Jul 22 '18 at 14:32
  • @Melardev Thanks for you input. As far as I tested (see SSCCE output link in answer below), specifying `JAVA_TOOL_OPTIONS` seems to work in Java SE and be passed through to Derby even in the Java EE server JVMs. – Kalle Richter Jul 23 '18 at 05:10

2 Answers2

4

Why don't you just use the JAVA_TOOL_OPTIONS env-variable? After setting export LC_ALL=de_DE.UTF-8 (in your .gitlab-ci.yml) you could set export JAVA_TOOL_OPTIONS="-Duser.language=en" and enjoy your error-messages in English.

Regarding "-Duser.language" not working for derby's startNetworkServer: startNetworkServer is a script that executes (in its simplest form) java -jar derby.jar. Because of that you cannot simply execute bin/startNetworkServer -Duser.language=en. But if you take a look at the startNetworkServer script, you can see that an environment-variable DERBY_OPTS is used. So probably it would also work to specify export DERBY_OPTS="-Duser.language=en", although I didn't try it that way. (and as your comment states, it doesn't)

sample .gitlab-ci.yml which works:

main:
    image: ubuntu:18.04
    script:
        - apt-get update && apt-get install --yes language-pack-de wget openjdk-8-jdk maven
        - export LC_ALL=de_DE.UTF-8
        - export JAVA_TOOL_OPTIONS="-Duser.language=en"
        - wget http://www-eu.apache.org/dist//db/derby/db-derby-10.14.2.0/db-derby-10.14.2.0-bin.tar.gz && tar xf db-derby-10.14.2.0-bin.tar.gz
        - cd db-derby-10.14.2.0-bin && bin/startNetworkServer &
        - mvn --batch-mode install
        - java -jar target/derby-embedded-data-source-locale-1.0-SNAPSHOT-jar-with-dependencies.jar

output:

$ java -jar target/derby-embedded-data-source-locale-1.0-SNAPSHOT-jar-with-dependencies.jar
Picked up JAVA_TOOL_OPTIONS: -Duser.language=en
running main
Exception in thread "main" java.sql.SQLNonTransientConnectionException: The connection was refused because the database database was not found.
        at org.apache.derby.client.am.SQLExceptionFactory.getSQLException(Unknown Source)
        at org.apache.derby.client.am.SqlException.getSQLException(Unknown Source)
        at org.apache.derby.jdbc.ClientDriver.connect(Unknown Source)
        at java.sql/java.sql.DriverManager.getConnection(DriverManager.java:677)
        at java.sql/java.sql.DriverManager.getConnection(DriverManager.java:228)
        at de.richtercloud.derby.embedded.data.source.locale.Main.main(Main.java:12)
Caused by: ERROR 08004: The connection was refused because the database database was not found.
        at org.apache.derby.client.net.NetConnectionReply.parseRDBNFNRM(Unknown Source)
        at org.apache.derby.client.net.NetConnectionReply.parseAccessRdbError(Unknown Source)
        at org.apache.derby.client.net.NetConnectionReply.parseACCRDBreply(Unknown Source)
        at org.apache.derby.client.net.NetConnectionReply.readAccessDatabase(Unknown Source)
        at org.apache.derby.client.net.NetConnection.readSecurityCheckAndAccessRdb(Unknown Source)
        at org.apache.derby.client.net.NetConnection.flowSecurityCheckAndAccessRdb(Unknown Source)
        at org.apache.derby.client.net.NetConnection.flowUSRIDPWDconnect(Unknown Source)
        at org.apache.derby.client.net.NetConnection.flowConnect(Unknown Source)
        at org.apache.derby.client.net.NetConnection.<init>(Unknown Source)
        at org.apache.derby.client.net.ClientJDBCObjectFactoryImpl.newNetConnection(Unknown Source)
        ... 4 more
ERROR: Job failed: exit code 1
FATAL: exit code 1
Halko Karr-Sajtarevic
  • 2,248
  • 1
  • 16
  • 14
  • Thanks for your input. However, [that doesn't seem to work](https://gitlab.com/krichter/derby-embedded-data-source-locale/-/jobs/82520730). @PaulHicks already stated that it's impossible to change the exception messages at runtime (i.e. with the described workaround or hacking the code only). I'd be good if you'd react to Paul's findings which contradict your solution as far as I understand. – Kalle Richter Jul 18 '18 at 06:31
  • Ok, it seems you're right, using `DERBY_OPTS` does not work indeed. But if you take a closer look at my answer, you have to set `export JAVA_TOOL_OPTIONS="-Duser.language=en"` directly after setting your `LC_ALL` env variable. I tried it using your `.gitlab-ci.yml` and it worked as expected. Updated my answer to include the `.gitlab-ci.yml`. – Halko Karr-Sajtarevic Jul 18 '18 at 07:19
  • 1
    You're right, I was confused. This solution seems to work, see https://gitlab.com/krichter/derby-embedded-data-source-locale-j4ee/pipelines/26281674 for details. Looks like this is a valid solution, thank you. – Kalle Richter Jul 23 '18 at 05:05
0

According what you described, Derby is apparently ignoring the user locale of the JVM (even when forced), and is instead using the locale defined at the OS-level.

You said:

Changing the system locale of the OS or a container the server could be wrapped into is a workaround, but not a solution.

I fully understand, but changing it (using an export LC_ALL), not on the container, but only inside the shell script starting Derby, isn't it a more acceptable workaround ?

TacheDeChoco
  • 3,683
  • 1
  • 14
  • 17