I'm trying to add multiple language support to the application. Is it possible to add languages at runtime, by creating new property file at runtime, pulling all the english text and calling google translator api to create the equivalent values and using native2ascii converter to change the values and put it in the property file?
Any better approach available to add languages at runtime??
Thanks
You can do that with a custom ResourceBundle implementation wherein you in turn provide a custom ResourceBundle.Control wherein you manage the loading and providing the values yourself. You can even provide them from the DB.
Then, to use it, just specify the FQN of the custom ResourceBundle instead in the <resource-bundle><base-name> or <f:loadBundle baseName>.
See also:
internationalization in JSF with ResourceBundle entries which are loaded from database
There's a few problems with java's i18n support. First, ResourceBundle.getBundle() can only look into two places for language support:
Properties files in the classpath
Class on the classpath
In either case, if you wanted to dynamically provide different languages on the fly (as they are requested), you'd most likely either have to:
Create a custom classloader so that loadClass and getResource could create these on the fly.
Use aspectJ to intercept the getBundle() method call and put some before advice on it to do what you want.
In contrast, spring's MessageSource framework is much more extensible, as MessageSource is an interface, and you can supply your own implementations and register them with the spring context, or nest them in other message sources, etc....
Related
I love the Spring properties loading mechanism. The fact that you can define several profiles and override or extend properties with other profiles, that you can use different file types (.properties, XML, JSON, ...) to store your properties, that you can use the value of other properties to resolve its own value, aso.
But to use the properties, you have to somehow initialize the Spring context (#SpringBootApplication or #SpringBootTest). And I would like to use this property loading mechanism in some libraries, where I cannot guarantee that the context is loaded (and I do not want to load it).
So, my question:
Can I somehow create a class that uses the Spring libraries to load the properties (on demand) in the same way Spring loads its properties?
Other classes will then use this class to access the properties. No need to load with annotations.
I was searching for this for some time, but I haven't found a solution, yet.
Would be great if so. knows a solution for that.
Regards, stay healthy and merry X-Mas!
The property lookup mechanism is defined by interface PropertyResolver, extended by interface Environment to support profiles, further extended by interface ConfigurableEnvironment to support PropertySources, i.e. the concept of searching through a set of property sources to find a property.
It is implemented e.g. by class StandardEnvironment, which defines property source for:
system properties
system environment variables
All the above are part of package org.springframework.core.env, i.e. part of the spring-core-XXX.jar file.
Support for application.properties files is added by class ConfigFileApplicationListener in package org.springframework.boot.context.config.
The class needs an instance of SpringApplication in package org.springframework.boot.
They are part of the spring-boot-XXX.jar file.
So, getting basic Spring property support is easy, just create a StandardEnvironment object.
Getting application.properties files loaded is deeply embedded in the Spring Boot code, and would be really difficult to do without initializing the Spring context.
I'm creating a JavaModule with some utilities class.
This module will used from some different Java Applications (these projects will be have the dependency into their pom files).
Into my JavaModule I would like to use some properties files to store the settings values. I con't use Spring int this module.
What's the best practice to use the properties files into a JavaModule without using Spring annotations?
Is it the correct way as reported in this example?
What's the correct place where I have to put the properties files? Can I use a dedicated folder?
Is there a way to override a specific value that it's contained into my Java Module's properties file from a Java Application that use my module?
I would use that logic, and afaik is the most common. But I was also in a project in which we used ResourceBundle even though it should be used to retrieve locale specific data, because it was less verbose.
In that case was just:
ResourceBundle.getBundle("properties").getString("my.property");
Once again. The example from mkyong would be my first choice for anything but a POC.
We load our translations from our database. To retrieve the bundles we have a custom java.util.ResourceBundle.Control.
To translate our e4 RCP application, I already created a TranslationService, which I add to the root context using an addon. That was no problem (only that I had to copy 95% of BundleTranslationProvider because I did not see any other way).
Now I want to use the new Message Extension (coming with Eclipse Luna) to translate the rest. As far as I can see from the sources of the default MessageFactoryServiceImpl, there does not seem to be an easy way to inject my ResourceBundle.Control there either.
In the linked blog series, the use case of getting the resource bundles from a database is described, but solved by using class based resource bundles. This is no option, because I can't implement a class for every resource bundle and every locale. The reason for loading the resource bundles from the database is to be able to deploy translations into new languages without redeploying the application.
Is the only way to achive this by creating my own IMessageFactoryService by copying 99% of the default MessageFactoryServiceImpl, just to pass our Control into the calls to ResourceBundleHelper?
After some investigation on this, I found a way that you are able to support your use case without modifying or copying code a lot.
You need to exchange the BundleLocalization to load the ResourceBundle your way. In your case by using your custom ResourceBundle.Control. By doing this you override that the platform is looking for the ResourceBundle specified by the MANIFEST.
At the moment you will also have to implement a custom TranslationService that uses your BundleLocalization. The existing BundleTranslationProvider does not take the BundleLocalization out of the context. And you will need to copy a lot of code there, because getBundle() is private. I will discuss possible modifications with the developers.
You can find an example here: https://github.com/fipro78/e4classbasedtranslation
Hope that helps you to solve your specific requirement.
AFAIK ResourceBundle.Control is used to load ResourceBundles. In the new Message Extension we use a custom ResourceBundle.Control to enable the loading of ResourceBundles in the OSGi context, and it is configurable via annotations.
AFAICS exchanging the ResourceBundle.Control will break any other use case supported by the new Message Extension.
The question is, why do you use a custom ResourceBundle.Control instead of creating a class based ResourceBundle? I haven't tried it yet, but maybe it is possible to create only the base ResourceBundle (without Locale information) and determine the Locale in another way than using getLocale().
But without knowing what you are doing in your custom ResourceBundle.Control, I don't know what to answer and what to suggest. Of course we could open the API for that, but as I said before, then every other plugin that makes use of the default implementation will fail.
Maybe you can give some hints on what you are doing exactly and I can show you a way to achieve your goal in another way.
This is more a general question by example:
I'm using xstream and woodstox, woodstox comes with a service provider for javax.xml.stream.XMLOutputFactory in woodstox jar registering com.ctc.wstx.stax.WstxOutputFactory.
I want to provide my own javax.xml.stream.XMLOutputFactory and still have woodstox jar in the classpath. I know I can provide my own with the system property javax.xml.stream.XMLOutputFactory , but I'm trying to take off the hassle from our dev ops team and do it with a service file in my jar or maybe in my war's META-INF/services folder. looking the code of javax.xml.stream.FactoryFinder how can I make sure that my
META-INF/services/javax.xml.stream.XMLOutputFactory file will be the one used by FactoryFinder?
we use xstream with camel and could not find a way to inject the factory to XStreamDataFormat
First: instead of relying on JDK SPI interface, I strongly recommend simplifying your life and NOT using it. It really adds no value over injecting XMLInputFactory and/or XMLOutputFactory yourself. For injection you can use Guice (or Spring); or just pass it manually. Since these factories do not have dependencies of their own, this is easy.
But if choose to (or have to) use XMLInputFactory.newInstance(), you can define a System property for "javax.xml.stream.XMLOutputFactory" and "javax.xml.stream.XMLInputFactory".
So why not use JDK approach? Multiple reasons:
It adds overhead: if you are not specifying System property, it will have to scan the whole classpath, and with big app servers this takes 10x-100x as long as most parsing
Precedence of implementations is undefined: if you multiple in classpath, which one will you get? Who knows... (and note: it might even change when you add new jars in classpath)
You are very likely to get multiple impl via transitive dependencies
Unfortunately, Oracle still seems to insist on adding this known-faulty method for registering service providers. Why? Probably because they do not have a DI lib/framework of their own (Guice is by google, Spring by Springsource), and they tend to be pretty control hungry.
You can just do like this to specify the XMLOutputFactory implementation You want to use:
System.setProperty("javax.xml.stream.XMLOutputFactory", ... full classname You want to use ...);
Source:
http://docs.oracle.com/cd/E17802_01/webservices/webservices/docs/1.6/tutorial/doc/SJSXP4.html
Deriving from JAXP, the XMLInputFactory.newInstance() method
determines the specific XMLInputFactory implementation class to load
by using the following lookup procedure:
Use the javax.xml.stream.XMLInputFactory system property.
Use the lib/xml.stream.properties file in the JRE directory.
Use the Services API, if available, to determine the classname by looking in the META-INF/services/javax.xml.stream.XMLInputFactory
files in jars available to the JRE.
Use the platform default XMLInputFactory instance.
I discovered that if I put the service file under
WEB-INF/classes/services/javax.xml.stream.XMLOutputFactory then it will be first in classpath and before jars in WEB-INF/lib.
and that's my solution.
We had similar issue where parsing would run in local but fail on server. After debugging found server is using reader com.ctc.wstx.evt.WstxEventReader
Whereas on local reader was com.sun.xml.internal.stream.XMLEventReaderImpl
We set following property to resolve it.
System.setProperty("javax.xml.stream.XMLInputFactory", "com.sun.xml.internal.stream.XMLInputFactoryImpl");
If your implementation is in a jar then make sure it is before woodstox.jar on the class path, then FactoryFinder will use your implementation.
We have a system where we wanted to consume the implementation of our interfaces in a separate jar. The scenario is clients consume our work and provide their own implementation to override default implementation.
The question is what is the best way to bind/wire the actual implementation classes into our system?
One way is let spring wire the dependencies. It is currently not an option since all clients are not using spring.
Looked into some options like resolving interface implementation classes using reflection. Not very happy with this solution.
Another good old option is configure the class name in one of the property and let clients configure it. It looks good.
But wanted to find some elegant option if available.
Also any idea how SLF4J / EL resolves their implementations automatically?
I'd suggest you to use SPI (Service Provider Interface).
It requires creating file that enumerates all available implementations of specific service. This may be annoying. Fortunately you can use this open source library that does this work for you: http://code.google.com/p/spi/
Perhaps the Reflections library is what you are looking for.
Reflections scans your classpath, indexes the metadata, allows you to query it on runtime and may save and collect that information for many modules within your project.
Using Reflections you can query your metadata such as:
get all subtypes of some type
get all types/methods/fields annotated with some annotation, w/o annotation parameters matching
get all resources matching matching a regular expression