I am working on a project where internationalized messages are retrieved using the #Value annotation.
e.g.:
#Value("${email.newUser.subject}")
private String NEW_USER_SUBJECT;
#Value("${email.newUser.message}")
private String NEW_USER_MESSAGE;
However, as part of my investigation, it appears that the #Value annotation is used to get a property from a property file and does not link into to automatic lookup of the correct version of the message.properties. Therefore as I understand it, this is only working by coincidence because we have currently only a single message.properties file.
Can anyone in the know tell me if I have the correct understanding of the situation?
The Answer is No, the #Value annotation is not part of Internationalization. It's use in conjunction with Internationalization is an error and will break when you try to change the Local.
Related
Using a application.properties file my Spring Boot app can use some property values in it. A way to make sure a mandatory value must present is to add an annotation #Value for the property. The problem with this is the app fails miserably if the property value is not there in the properties file.
I am after a nicer less horrible way to say printing out a log line about "Property A is missing" instead of a whole stack trace. Is there a way to do this while still using #Value to initialise the properties? For example, property A is mandatory, an error is logged before app exits; property B is missing but not mandatory, a warning is logged and app continues.
If you can identify all property, then you can write a method in Application class with #Postconstruct, and inside your method, you can manually validate and log them
#Autowired
private Environment environment;
#PostConstruct
private void validateProperties() {
environment.getProperty(key);
.....
......
}
Alternatively, you can write your custom EnvironmentPostProcessor, and iterate all properties and log whichever is null/empty.
As you're using spring-boot consider creating a #ConfigurationProperties class rather than using the #Value annotation.
By doing that you can do your validations using Bean Validation, also in the same class, you can implement the interface InitializingBean and add extra validations/log messages as you with.
Follow this link on Spring's official docs to read more about #ConfigurationProperties.
My project is using application.properties file to set the property as following: spring.jackson.deserialization.fail-on-unknown-properties=true, which works in all cases but one:
class Model {
#JsonUnwrapped
public SubModel subModel;
}
simply commenting out the annotation causes ObjectMapper to fail as intended, but as soon as the annotation is added, the option set seems to be ignored.
How can I configure jackson to use annotations along with the config?
Due to logic needed to pass down unwrapped properties from parent context, there is no way to efficiently verify which properties might be legitimately mapped to child POJOs (ones being unwrapped), and which not.
As of now it is not possible to make jackson to fail on unknown property with unwrapping.
Issue is still open ,
https://github.com/FasterXML/jackson-databind/issues/650
How can I configure jackson to use annotations along with the config?
It is nothing to do with config or annotations, they are working fine.
The default behaviour for the resource key look seems to be to prefix the field name with the constraint. I would like to post fix it instead.
public class MyForm {
#NotEmpty
private String name;
}
In my messages.properties:
myForm.name=The label
NotEmpty.myForm.name=Please enter your name
I would like to use:
myForm.name=The label
myForm.name.NotEmpty=Please enter your name
This obviously purely cosmetic, but my OCD can't handle the look of my resource file.
I'm using spring 3.1.2 with hibernate validator 4.3.0.Final. The application it's self is using the #Configuration, #EnableWebMvc and WebMvcConfigurerAdapter style configuration, but I should be able to translate any xml based solution.
A simple idea is to extend DefaultMessageCodesResolver and override the method postProcessMessageCode() which originally is:
protected String postProcessMessageCode(String code) {
return getPrefix() + code;
}
and change it the way you desire. I believe Spring will pickup your bean of type MessageCodesResolver as the default behavior when bootstrapping. Hope this helps.
In Spring 3.1+, now you can configure a message codes resolver through <mvc:annotation-driven />. It seems that support for the Java API will come in 3.2.
I'm studying Spring 3 and I'm using it in a simple web-application.
Now I'm implementing a Spring MVC Controller using annotations, and I'm wondering:
Is there any best practice using #RequestMapping annotation?
I mean: I've seen that usually the URL mapped in this annotation is hardcoded in the class...
Is there a way to pass the URL in a 'loosely coupled way' (to obtain a more reusable class)?
I know that there are some wild cards that can be used, but I think that isn't the solution... Am I wrong?
EDIT:
I add an example to better explain my doubt.
Suppose I want my controller to be triggered by a request to /foo/bar/baz/mypage.htm, in my controller the handler method will be annotated with #RequestMapping("/foo/bar/baz/mypage").
Now I decide to change the URL triggering my controller into /foo/bar/otherpage.htm, so i need to edit my class, put #RequestMapping("/foo/bar/otherpage") on my handler method, recompile the project and deploy it again.
It seems to me not so practical...
Currently annotated controllers aren't very configurable.
As far as I know, the only possible approach to this problem is to use alternative HandlerMappings in order to configure "base URLs" of controllers. For example, as follows:
// Note the absense of #Controller to prevent this controller
// from being discovered by DefaultAnnotationHandlerMapping
public class FooController {
#RequestMapping("/list") public String list(...) { ... }
#ReqeustMapping("/save") public String save(...) { ... }
}
.
<bean
class = "org.springframework.web.servlet.mvc.support.ControllerBeanNameHandlerMapping" />
<bean name = "/foo" class = "FooController" />
<bean name = "/bar" class = "FooController" />
In this example two instances of FooController handle /foo/list, /foo/save, /bar/list and /bar/save respectively.
The upcoming Spring 3.1 will have an improved Spring 3.1 architecture (Spring 3.1 M2: Spring MVC Enhancements) that seems to be more flexible, though I haven't checked it yet.
I think you are trying to solve the wrong problem. If you wanted to change the pages that matched a controller you'd need to change a file somewhere. Would you rather change the file with the related code underneath it, or would you rather work with some XML files that specifies the URL and the class, and then you have to worry about the file being in the right place during runtime?
As there should be almost no code in your controller anyway, you should think of your controllers as compilable configuration files. Also, if you are using a build system like Maven or Ant and not compiling individual files by hand using Javac then compilation time shouldn't be an issue. If it becomes one, it's probably time to split your project into sub-projects.
I think you should just embrace this and see that it is probably not the issue you think it is. Also, did you know that controllers can match to expressions and not just literal strings? That gives you some flexibility in your naming.
If you really want to, you could just fall back to the Spring 2.0 style XML configuration, but I don't think anyone would recommend that.
I think that is not a best practice, but have you tryed with #PathVariable annotations?
#RequestMapping(value="/path/{word}", method=RequestMethod.GET)
public ModelAndView myRestMethod(#PathVariable String word) {
...
}
There is a property of type Resource in my Spring 3 bean that should be injected with a reference to a file in the classpath. I use the #Value annotation as below to hopefully achieve this.
public class TestBean
{
#Value("classpath:/abc/student/test.sql")
private Resource SqlFile;
...
}
But the property is always null. I have confirmed that the sql file has been deployed in the maven target directory (it is at target/classes/abc/student/test.sql).
The closest solutions that I could google were this and this which detail the xml way whereas I am interested in doing this using annotations.
Appreciate any pointers on what could be wrong here.
Thanks,
Vijay
If it's going to be hard-coded like that, then just
private Resource sqlFile = new ClassPathResource("/abc/student/test.sql");
Otherwise, what you're really after is
#Value("${some.property}")
private Resource sqlFile;
and I believe that in injecting the property value, the correct PropertyEditor will be applied.
If you don't want to specify a property then this should work
#Value("${:classpath:json/inventory.json}")
Resource inventory;