Restricting Java maven plugin configuration parameters - java

I’m writing a maven plugin with a number of configurable parameters. There are a number of parameters specified in the Mojo class. One of these parameters is required and must contain certain values (let’s say, either ‘Atwood’ or ‘Spolsky’). At the moment it is annotated with a. #required field as shows here:
public class GenerateMojo extends AbstractMojo{
...
...
/**
*#parameter
*#required
*/
private String someParameter;
...
...
}
Which is all well and good, but if someone forgets to include the parameter they get a generic error message like so:
Inside the definition for plugin 'xyz' specify the following:
<configuration>
...
<someParameter>VALUE</someParameter>
</configuration>
If is possible to either (1) restrict the values that can be inputted to the someParmeter field to give a better error message, or (2) specify the error message myself so that I can write something like “The value for ‘someParameter’ needs to be either ‘Atwood’ or ‘Spolsky’ ??
Thanks

There is an open Jira to add support for enumerations to parameter values in Maven 2.2 (it is already supported in Plexus on Java 5).
You can specify a default value so at least the Mojo won't fail in initialisation. You can then validate the value of the parameter in the execute() method and output a more helpful message.
If there is no sensible default, you can set the default to a value that will be invalidated in the execute() method, this effectively means the user will have to define it, and they get a meaningful error message. For example:
/**
* #parameter expression="${someParameter}" default-value="_"
*/
private String someParameter;

Related

How does Spring interpolate ${x} inside a string?

I have a java class in a Spring project that looks (edited) like:
#Component
public class X
{
private static final ApplicationContext CTX = new FileSystemXmlApplicationContext("file:${PATH}/ApplicationContext.xml");
...
I am looking for the reference explaining how the ${PATH} is interpolated in the string parameter. The PATH is passed as a system property ( java -DPATH=...) so I assume it takes it from there but I can't find an explanation describing the mechanism. Is it a Spring related feature similar to the syntax used in #Value?
configLocations (type String) passed to one of the FileSystemXmlApplicationContext constructors are processed by the resolvePath() method inherited from the AbstractRefreshableConfigApplicationContext class.
resolvePath() documentation says:
Resolve the given path, replacing placeholders with corresponding environment property values if necessary. Applied to config locations.
See Also:
PropertyResolver.resolveRequiredPlaceholders(String)
resolveRequiredPlaceholders() documentation says:
Resolve ${...} placeholders in the given text, replacing them with corresponding property values as resolved by getProperty(java.lang.String). Unresolvable placeholders with no default value are ignored and passed through unchanged.
The PropertyResolver declaring that getProperty() method is actually a StandardEnvironment.
StandardEnvironment documentation says:
Environment implementation suitable for use in 'standard' (i.e. non-web) applications.
In addition to the usual functions of a ConfigurableEnvironment such as property resolution and profile-related operations, this implementation configures two default property sources, to be searched in the following order:
system properties
system environment variables

Java annotations: pass value of annotation attribute to another annotation

I have interface Resource and several classes implementing it, for example Audio, Video... Further, I have created custom annotation MyAnnotation with Class type param:
#MyAnnotation(type = Audio.class)
class Audio {
...
}
#MyAnnotation(type = Video.class)
class Video{
...
}
In some other place in code I have to use Interface Resource as a returned type:
public class Operations<T extends Resource> {
....
#OtherAnnotation(type = Audio.class (if audio), type = Video.class (if video) )
T getResource();
....
}
The question is how to appropriatelly annotate annotation #OtherAnnotation depending of what kind of Resource type will be returned ?
What you are asking is for dynamic values for annotation attributes.
However annotations can only be set at compile time which is the reason why their values can only be compile time constants. You may only read them at runtime.
There was a similar question in which someone tried to generate the annotation value , it's answer explains why there is no way to dynamically generate a value used in annotation in a bit more detail. In that question there was an attempt to use a final class variable generated with a static method.
There are annotation processors which offer a bit more flexibility by handling placeholders. However i don't think this fits your case, as you want the dynamic values at runtime.
This answer refers to spring's use of the expression language for the Value annotation in which the placeholder (#Value("#{systemProperties.dbName})") gets overrided with the data from one of the property sources defined ( example in spring boot )
In any case, you will have to rethink your architecture a bit.

Hibernate's validateValue() throws illegal argument exception if a property has no rules?

I have the following class:
class Foo
{
#NotEmpty
private String member1;
#NotEmpty
private String member2;
private String member3; //this one is optional, so has no rules
}
I have a library to which I add all the property names and corresponding UI fields, each time the UI's onChange event occurs, I call validateValue() on the given field name for that field, to validate it and show error/success message.
The problem is, in this case where I have no rules for member3, if I try to validate it by doing this:
String value = event.getValue(); //whatever the new value is now
validator.validateValue(Foo.class, "member3", value);
On the 2nd line, I get the following exception:
Caused by: java.lang.IllegalArgumentException: member3 is not a valid property of
com.xxx.Foo
Both member1 and member2 within the same class, are validated correctly.
Is there anything I can do to avoid getting this exception on the fields that don't have any rules set on them? If not, is there a way (without reflection or specifying it manually for each field) to check if a rule has no rules set on it, so i can avoid calling validateValue on it?
Which version of Hibernate Validator are you using? I checked with the latest version (5.1.0.Final) and there it works. If you can I recommend you upgrade.
You can also create an issue in the Validator issue tracker, reporting your problem and in particular which Validator version you are using.
Last but not least, to answer your question about alternatives. You could use the Bean Validation metadata API to find the constrained properties:
validator.getConstraintsForClass(Foo.class).getConstrainedProperties()
This will allow you to process only the properties which are acually constrained.

How do I debug what's wrong when the Endpoints framework stops generating the WEB-INF/*.api-file?

Given a Google Cloud Endpoints project in Eclipse with the servlet-class annotated with #Api(name="helloworld"), the Endpoints framework generates a file named war/WEB-INF/helloworld-v1.api when the project compiles successfully. Sometimes this file is not generated even if there are no compilation errors though - only what I will call "GAE Endpoints code convention errors".
Example - working:
public class TestEntity {
public String Text;
public TestEntity(String text){
Text = text;
}
}
#ApiMethod
public TestEntity getTestEntity(){
return new TestEntity("Hello world");
}
Example - NOT working:
// The TestEntity-class is unchanged
#ApiMethod
public TestEntity getTestEntity(String input){
return new TestEntity("Hello world");
}
The problem with the latter example is that I take a String parameter as input without annotating it with #Named. I know that in this example, but there might be other cases where this is not so obvious.
Is there anywhere where I can read some sort of error log on why the .api file is not generated?
Although I am a fan of code by convention, it really takes the programming efficiency a step back if I cannot get feedback on what I do wrong. Eclipse provides compiler error feedback. The Google Cloud Endpoints Framework should provide Code-By-Convention-Rule-Breaking feedback.
There isn't currently good logging or error messaging when code generation fails, though it's one of the (if not most) requested features. In the interim, here's a list of the common failure cases:
The return type is invalid. Return types must be objects conforming to JavaBean conventions, and types like Object, String, and Integer are not allowed.
One or more argument types are invalid. Methods may accept at most one object in the POST body, and this object should also conform to JavaBean conventions. Methods may accept zero or more arguments via the query string (using the #Named annotation) and these must be scalar types (e.g. String, Integer).
An API, method, or parameter has an invalid name. APIs, methods, and parameters should be named to match the following regular expression: [a-z]+[A-Za-z0-9]*. Convention also suggests using lowerCamelCase for naming (though alllowercase is allowed).

how to pass request parameters to a java annotation

i am using play framework , i need to check the user's permissions with #secure annotation , but i get a problem here :
#secure(UID=???)
public static void removeFavorite(Long storyId,Long userId){
}
can any one tell me how to pass the "userId" parameter to "UID" in the annotation ?
PS : the "userId" parameter is in request scope.
many thanks!
AFAIK you can't change annotations at runtime (at least not without dynamic code generation). Additionally, annotations are static, i.e. they apply to classes or class members (fields, methods etc.) and can't be changed per instance. Thus you can't pass the userId to that annotation.
I dont know what#securedoes, but generally, you'd read the annotation at runtime and optionally check its static parameters and if those checks succeed you'd read theuserId` parameter and do whatever is appropriate when that annotation is present.

Categories