GWT Maven Plugin: Generating Non-String Parameters in the Messages Class

I have a property in my "Messages.properties" file that has an argument that uses number formatting:

my.message=File exceeds {0,number,0.0}MB. 

When I run the gwt:i18n Maven target, it generates a Messages interface based on the properties in my Messages.properties file (as usual):

 public interface Messages extends com.google.gwt.i18n.client.Messages { //... @DefaultMessage("File exceeds {0,number,0.0}MB.") @Key("my.message") String my_message(String arg0); //... } 

The problem is that the method parameter is String . When I run the application, it gives me an error because the message argument is expecting a number, but a string is provided (error message: "Only number subclasses may be formatted as a number").

How to configure Maven to change this parameter to a number (e.g. float or Number )? Thanks.

+6
source share
2 answers

Given the above, I decided to supplement my previous answer. First of all, as far as I know, you cannot use the existing i18n Maven target (and GWT I18NCreator) to complete tasks. Secondly, after learning a little more about the generator solution that I proposed, I found that:

  • Michael is right that you will not pick up errors during compilation using the property search interface method (sin in GWT), as suggested above. However, this is still the easiest / fastest way to do this.
  • You can provide compile-time checking by writing your own interface, which is kept up-to-date with the properties file, having one method for each property, and then getting a generator to write the class that implements this interface. notification that when you change a property in the properties file you only need to change the interface that you wrote. If you have written the generator correctly, it will no longer have to be changed! The best way to go about method names probably follows GWT: if the.prop.one property is called, then the method name is the_prop_one (..).
  • If you really do not want to support the interface manually, I see that you can write your own version of I18NCreator. This is because the maven i18n target is not a GWT parameter compiler, but a call for the maven plugin to write
    Message / constant interfaces based on property files found in the class path. Therefore, if you write your own I18NCreator, you will also need to write a Maven plugin, which you can use to call it before compiling the GWT application. Or, to make it easier, you can just start your I18NCreator manually (using the good java command to run this) every time you change the keys of the properties file (of course,
    there is no need to run it when only the actual messages change).

Personally, I would just write and save my properties file and an interface that displays it manually. The Generator will always search for the properties file and generate methods that match the properties (with any arguments required based on the actual message), therefore, if the interface you wrote reflects the properties file, the class generated by the Generator will always implement it correctly.

+2
source

It seems to me that this function is not supported by the GWT I18NCreator (this is what causes the maven i18n target). To do this, you will have to write your own generator. I wrote a couple of generators, and it's not as complicated as you think. In your case, you would like to write a generator that creates an instance of the interface similar to GWT messages (but you can use your own), but which has additional functions that you want to use when decoding messages. The following guide, which will help you, may help you, since it seems to be pretty much what I did and it works:

http://groups.google.com/group/Google-Web-Toolkit/msg/ae249ea67c2c3435?pli=1

I found that the easiest way to write a GWT generator is to actually write a test class with the code that you want to generate in your IDE (and using autocompletion, validation syntax, etc.), and then in the past / adapt it to to a writer like this:

 writer.println("public void doSomething() { /* implement */ }"); 

And do not forget to tell your module (module.gwt.xml file) which interface you need to create and with which class, for example:

 <generate-with class="mycompany.utils.generators.MyGenerator"> <when-type-assignable class="mycompany.messages.MyCoolPropertiesReader" /> </generate-with> 

In Generator code, you can use Java with all its great features (not limited to GWT-translatable code), so it’s easy for you to implement what you want. In client code, you can simply do:

 public interface MyCoolPropertiesReader { public String getMessage(String propKey, Object... parameters); } public class MyClientSideClass { MyCoolPropertiesReader reader = GWT.create(MyCoolPropertiesReader.class); String msg = reader.getMessage("my.message", 10); // do more work } 

The test generator that I wrote (GWT "reflective" getter and setter, as it were) looks like this:

 public class TestGenerator extends Generator { @Override public String generate(TreeLogger logger, GeneratorContext context, String typeName) throws UnableToCompleteException { try { TypeOracle oracle = context.getTypeOracle(); JClassType requestedClass = oracle.getType(typeName); String packageName = requestedClass.getPackage().getName(); String simpleClassName = requestedClass.getSimpleSourceName(); String proxyClassName = simpleClassName + "GetterAndSetter"; String qualifiedProxyClassName = packageName + "." + proxyClassName; System.out.println("Created a class called: " + qualifiedProxyClassName); PrintWriter printWriter = context.tryCreate(logger, packageName, className); if (printWriter == null) return null; ClassSourceFileComposerFactory composerFactory = new ClassSourceFileComposerFactory(packageName, className); composerFactory.addImport("test.project.shared.GetterAndSetter"); composerFactory.addImplementedInterface("GetterAndSetter<" + underlyingTypeName + ">"); SourceWriter writer = composerFactory.createSourceWriter(context, printWriter); if (writer != null) { JField[] fields = requestedClass.getFields(); for (JField field : fields) { createSetterMethodForField(typeName, writer, field); } writer.indent(); writer.println("public void set(" + typeName + " target, String path, Object value) {"); writer.indent(); createIfBlockForFields(writer, fields, true); writer.outdent(); writer.println("}"); writer.println(); writer.println("public <K> K get(" + typeName + " target, String path) {"); writer.indent(); createIfBlockForFields(writer, fields, false); writer.outdent(); writer.println("}"); writer.println(); writer.outdent(); writer.commit(logger); } return packageName + "." + proxyClassName; } catch(NotFoundException nfe) { throw new UnableToCompleteException(); } } } 

Hope this helps you.

+1
source

Source: https://habr.com/ru/post/899818/


All Articles