This is a question of best practices for externalizing error messages.
I am working on a project where we have errors with codes, short descriptions and severity. I was wondering what the best way to externalize such descriptions is. What comes to my mind is to have them in code which is bad, to store them in database, to have them in property files, or maybe to have a static class loaded with descriptions. I think I will go with properties, but maybe there is a better way of doing it.
Thanks
Use a ResourceBundle to store those messages (and other user interface messages such as button and label text, accelerators, shortcuts, and so on). Here's a short example assuming that you have a bundle named ErrorMessages with an error named error.NameOfErrorMessage and a JFrame in the variable frame.
ResourceBundle errorMsg = ResourceBundle.getBundle("ErrorMessages");
String currError = errorMsg.getString("error.NameOfErrorMessage");
JOptionPane.showMessageDialog(frame, currError);
For more information you can see About the Resource Bundle Class in the internationalization tutorial.
We were faced with a similar issue. You are right that having the messages in the code is a poor choice. We found that a couple of factors influenced which alternative is better. In our case, we needed to have the same error codes handled in Java on the client side, and in SQL and Perl code on the server side. We found it useful to have a central definition so we used a data base.
If you only need to process the error codes in Java, a properties file or resource bundle is probably the most flexible, since they allow for localization and/or internationalization. I'd stay away from a static class; although it is better than in-line error descriptions, it is still relatively inflexible.
I suppose that there are some many ways to do this correctly.
The most common way I see is the use of external files that relates internal error codes in your actual code and a description something like
error.123="Error with data X"
warning.1="You must use ..."
To change the text error on your app you only need to change this text file. This is the way internationalization works
error.123="Error con el dato X"
warning.1="Deberías usar ..."
Related
I'm looking for a way to prevent some sensitive data from being logged.
Ideally i would like to prevent / capture things like
String sensitive = "";
log.info ("This should be prevented or caught by something : {} ", sensitive);
this post is a bit of a longshot, I'm willing to investigate on any lead.
annotation, new types, Sonar Rules, logger hacking etc...
thx for your brainstorming :)
guillaume
Create custom type for it.
Make sure that toString doesn't return actual content.
I imagine there are multiple ways to do this, but one way is to use the Logback configuration file, to specify a message provider for the "arguments" and "message". In those providers, you define a "writeTo" method that looks for particular patterns in the output, and masks them.
This is the path to a solution, but I obviously don't provide many details here. I'm not aware of any "standard" solutions for this.
Another possibility would avail itself if your architecture has services running in transient containers, and the log output is sent to a centralized log aggregator, like Splunk. If you were ok with the initial logs written in the container having sensitive data, you could have the log aggregator look for patterns to mask for.
I would recommend two options, can you split your PII data into a separate log and then log that data securely?
If not, consider something like Cribl Logstream. Point your log shipper at it and let it strip away any PII you are concerned about. LogStream makes it very very easy to remove/mask/encrypt sensitive data. It has all sorts of other features as well.
At my last job we used LogStream as the router to make decisions about the data based on the content. PII data was detected and one copy was pushed to a secure PII certified logging platform and another copy was pushed to the operational logging platform but the PII data was masked so a wider audience could use the logging with no risk. It was a very useful workflow that solved a log of problems.
I'm wondering what the drawbacks are for using strings that are defined in the java files in Android code.
I like to use plain old Java strings for things that are not visible strings like e.g. names in XML documents that I'm parsing, or keys for bundles. Seems to be a good idea to just keep all those things in the java file where they are used instead of moving them out into an XML file and making the code more complicated.
Yet, I see many examples of Android code that seem to put every string into a resource file.
What's the issue with having strings in java files? What are the reasons that people don't do it? I've been doing it in my apps and haven't seen any issues yet so far.
Note that I'm aware that XML files make a ton of sense for stuff that needs to be translated. This question is for cases where the strings stay the same.
Let me try to make this question clearer:
Are there any reasons except:
Because it's a standard / best practise etc. - my question is basically: why is it a best practise, only because of i8n, or are there other reasons?
Because it allows you to use the resources framework for translation, device-dependent strings etc.
Because it allows you to use non-ASCII characters.
The simple answer to your question is its a standard to put all your string into resource. Also there are many reason that if you are keeping your string in xml/java file you have to update each and every reference in these file for a single string.
for eg. if You want to change "Ok" to "confirm" which are used in 5 different file you have to change in all those 5 files but for String resource you just have to update one file which string.xml.
Edit
Please find below some of reasons we should use String.xml
1) To update single reference to multiple occurrences. As according to the #treesAreEverywhere It can be done with public static String, but it will take memory on startup of application and till application is closed. But String written in String.xml will be loaded at time of use.
2) Multiple language support. You can create multiple language resource folder to support your multiple language application so language changed using Locale will be dynamically maintained by OS at run time according to language resource folder.
3) Please check Localization document which provide you more information about using string.xml
4) Strings don’t clutter up your application code, leaving it clear and easy to maintain.
It's a kind of coding standard like any other language has. But you can ignore it if you want and can create your code with public static string variable in code. It is not compulsory to use string.xml but its a good coding practice to use it. Good practice like closing the if block with parenthesis containing single statement rather than leaving it as it is.
if(condition){ statement; } rather than if(condition) statement;
Actually, good practices is a good reason to do it, but there are more.
For example, one reason that I can recall right now is that strings.xml is UTF-8 codified. Hardcoded strings doesn't show some characters properly.
The purpose of strings.xml (and other *.xml resource files) is to regroup similar values in one place. This facilitates finding values that would be otherwise buried in the code. Those resource files also makes the maintainability better, since a modification to one value can have app-wide effects (such as changing the title of the app or the theme). Finally, as you mentioned, it provides a framework for translating your app to other languages.
If you know your app will not be translated and won't be modified, it's not a bad thing to hard-code them. However, if you think your app will get a lot of updates, it is better to start using good foundations and use XML resource files.
Besides these reasons and the ones mentioned by #Zinc (which I am unaware of and cannot confirm), there are no other reasons regarding why you would want to use XML resource files.
The drawback of using resource files is that is is theoretically is slower and requires a bit more memory. Read android - strings.xml vs static constants and Does hard coding of string affect performance?
If you put all your strings which are related to your application, then you can implement I18N kind of applications very easily and it is very useful while doing application changes (Company takeover some other company). It is just change names in xml files. No need to touch any java file.
I am working on a new project that has about 100 error codes and corresponding messages.
The way it was done before is to use a constants class with all these codes and messages as final Strings.
Personally, I don't like the idea as addition/removal of error codes requires a code change.
Other option I have is to create a cache(HashMap) of these error codes loaded from a properties file or from a database.
What is the most efficient way to maintain a list of error codes ?
For 100 error codes I think it is easier to go with the properties file, and use a Properties object. http://docs.oracle.com/javase/6/docs/api/java/util/Properties.html
You can do it with a database too, but assuming you use JDBC you have to connect/select data/process result set/close resources, so it is a little more complicated.
For many projects I have worked on, programming teams work with the style of placholding every piece of static text in an xhtml file into a properties file. For example:
xhtml=
...
<h1>${messages.resourceBundle['key.to.static.text.placeholder']}</h1>
...
messages.properties=
...
key.to.static.text.placeholder=This will be the heading for this page only
...
Would anybody be able to explain what the advantage in this is?
So far, I can only see the following disadvantages:
making changes to any xhtml file requires you to hunt for the correct .properties file, and then the individual property to make the change to
if others have re-used properties, then deleting them becomes tricky as you have to be certain no other page is referencing the property, therefore after several change request rounds, properties files become large with redundant properties
if there are 1000 xhtmls, there will be 1000 .properties files to load, which is more cycles on the cpu to load and inject static pieces of text
if your using WebFlow and have flows that pass into other flows, properties have to be duplicated, meaning that sometimes you must place the same property in many different properties files to render correctly
hard to read code; if you know you want to work on the text 'This will be the heading for this page' only, you'll need to work out where that is on the xhtml from the property files first - you can't simply look at the xhtml and see clearly how the content will be laid out once rendered.
The only advantages I can see are text reuse and possibly html escaping.
Apologies if its coding 101, but I've had a hunt around Google and can't find the reasoning to the pattern.
Many Thanks
This is a common practice for internationalizing content.
You create one property file per language (or locale) and use a dynamic way off resolving which one to load depending on the context. (e.g. Language HTTP header the browser sends).
It is arguably more flexible than providing 1 jsp file per language, and can still deal with complex cases where plurals or stylistic differences might change the way you write localized text.
This is a standard JDK feature, lookup resource bundles.
You do not have to build 1 file per jsp (maybe your framework works this way?), although doing so can help the person writing the translation.
In GWT one typically loads i18n strings using a interface like this:
public interface StatusMessage extends Messages {
String error(String username);
:
}
which then loads the actual strings from a StatusMessage.property file:
error=User: {0} does not have access to resource
This is a great solution, however my client is unbendable in his demand for putting the i18n strings in a database so they can be changed at runtime (though its not a requirement that they be changed realtime).
One solution is to create a async service which takes a message ID and user locale and returns a string. I have implemented this and find it terribly ugly (it introduces a huge amount of extra communication with the server, plus it makes property placeholder replacement rather complicated).
So my question is this, can I in some nice way implement a custom message provider that loads the messages from the backend in one big swoop (for the current user session). If it can also hook into the default GWT message mechanism, then I would be completely happy (i.e. so I can create a interface like above and keep using the the nice {0}, {1}... property replacement format).
Other suggestions for clean database driven messages in GWT are also welcome.
GWT's in-built Dictionary class is the best way to move forward. Here's the official documentation on how to use it.
Let's say your application has 500 messages per locale at an average of 60 chars per message. I wouldn't think twice about loading all of these when the user logs in or selects his language: it's <50k of data and should not be an issue if you can assume broadband connectivity being available...your "one swoop" suggestion. I already do that in one GWT application, although it's not messages, but properties that are read from the database.
i think you might find this article useful:
http://googlewebtoolkit.blogspot.com/2010/02/putting-test-data-in-its-place.html?utm_source=feedburner&utm_medium=feed&utm_campaign=Feed:+blogspot/NWLT+(Google+Web+Toolkit+Blog)&utm_content=Google+Reader
What you could do is set up a TextResource and then, you could just change the text at runtime. I haven't tried this but I am very confident that this would work.
To optimize the performance, you can put your messages in a js resource, for example: http://host.com/app/js/messages.js?lang=en, then map this resource to a servlet which will take the messages dictionary from your cache (a singleton bean, for instance) and write it to the response.
To optimize even more, you can:
- put a parameter to the resource URL, for example: .../messages.js?lang=en&version={last updated date of messages}
- {last updated date of messages} is stored somewhere in DB
- whenever user updates the messages, {last updated date of messages} will change
- in the response to browser, set Cache-control as you want to tell browser to cache your messages.