Invalid property exception in spring - java

I am using spring in my application , When i am loading the springApplicationContext to get the beans i am getting the errors
Caused by:
org.springframework.beans.InvalidPropertyException:
Invalid property "abc"
Even though there is a property abc and the setter for that property in the bean.
This is a weird error i know , but i can't figure out where is the problem.
Any pointers will be helpful.
Thanks!
Pratik

Ensure that the property has both a public setter and getter. In case of an AnyObject property it should look like:
private AnyObject abc;
public AnyObject getAbc() { return abc; }
public void setAbc(AnyObject abc) { this.abc = abc; }
There is however one special case: in case of a boolean property it should look like:
private boolean abc;
public boolean isAbc() { return abc; }
public void setAbc(boolean abc) { this.abc = abc; }
Note the is prefix instead of get.

I remeber the similar question at Spring forums. It was found out that there was a setter signature like
public class MyClass {
private Aggregated field;
public MyClass setField(Aggregated field) {
this.field = field;
}
}
I.e. the setter's return type was not void.
Anyway, Spring uses standard Instrospector for processing class properties. Try it with your class and check if target property is found.

Related

Access annotation attributes from custom oval annotation

Is it possible, when using custom oval annotation and custom class for check, to access the annotation and retrieve the used annotation attributes ?
Reference for oval: https://sebthom.github.io/oval/USERGUIDE.html#custom-constraint-annotations
Minimal example
Lets assume we have class Foo.
It has two annotated fields.
Each time, the annotation has a different myValue – a and b.
class Foo {
#CustomAnnotation(myValue = "a")
public String first;
#CustomAnnotation(myValue = "b")
public String second;
}
This is the annotation.
It is noted that a check should be performed using MyCheck.class, also setting some default value for myValue.
#Retention(RetentionPolicy.RUNTIME)
#Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD})
#Constraint(checkWith = MyCheck.class)
public #interface CustomAnnotation {
String myValue() default "";
}
Now we want to use oval to validate this field.
Most importantly, we want to extract the value a or b from the annotation's myValue and use it inside our validation logic.
public class MyCheck extends AbstractAnnotationCheck<CustomAnnotation> {
#Override
public boolean isSatisfied(Object validatedObject, Object valueToValidate, OValContext context,
Validator validator) throws OValException {
// how to get the value of `myValue`, which is `a` or `b` or empty string as default
}
}
What I have tried and failed:
validatedObject is Foo.class. You can easily get its fields and annotations. However, there is no way to differentiate between the two annotations.
valueToValidate is in this case String value – what first or second holds.
context not useful, you can get compile time type from it, which is String
validator not useful ?
After some digging in the superclass I have found that you can override method
configure
This method gets as the only parameter the annotation that is currently being checked at the field.
You can then read the myValue.
public class MyCheck extends AbstractAnnotationCheck<CustomAnnotation> {
private String myValue;
#Override
public void configure(CustomAnnotation customAnnotation) {
super.configure(customAnnotation);
this.myValue = customAnnotation.myValue();
}
#Override
public boolean isSatisfied(Object validatedObject, Object valueToValidate, OValContext context,
Validator validator) throws OValException {
if (myValue.equals("a")) {}
else if (myValue.equals("b")){}
else {}
}

Jackson - #JsonCreator return generics

I want to integrate vavr validation library in my command dto's in a way that when command dto is deserialized from request, return type of the static factory will be Try but jackson is throwing following error :
Type definition error: [simple type, class com.foo.command.FooCommand]; nested exception is com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of com.foo.command.FooCommand (no Creators, like default construct, exist): cannot deserialize from Object value (no delegate- or property-based Creator)
Here is FooCommand
#AllArgsConstructor(access = AccessLevel.PRIVATE)
public final class FooCommand {
private String foo;
private String bar;
#JsonCreator
public static Try<FooCommand> of(
#JsonProperty("foo") String foo,
#JsonProperty("bar") String bar
) {
return Try.of(() -> {
//Validate values
});
}
}
I am using spring 5 and it's annotated to deserialize request body automatically into controller parameter.
Is something like this possible ? Thanks in advance.
I had a similar problem that I fixed by using Converters: Using Jackson, how can I deserialize values using static factory methods that return wrappers with a generic type?
I haven't yet found how to apply the converters automatically, so you have to annotate every occurrence of the wrapped type in your requests.
public class Request {
#JsonDeserialize(converter = FooCommandConverter.class)
Try<FooCommand> command;
}
You can write a Converter like so:
public class FooCommandConverter
extends StdConverter<FooCommandConverter.DTO, Try<FooCommand>> {
#Override
public Try<FooCommand> convert(FooCommandConverter.DTO dto) {
return FooCommand.of(
dto.foo,
dto.bar
);
}
public static class DTO {
public String foo;
public String bar;
}
}

Converting configuration properties to enum values

I have a configuration file which contains this line:
login.mode=PASSWORD
and an enum
public enum LoginMode {
PASSWORD, NOT_PASSWORD, OTHER }
and a spring bean
<bean id="environment" class="a.b.c.Environment" init-method="init">
<property name="loginMode" value="${login.mode}"/>
</bean>
and of course a bean class
public class Environment {
private LoginMode loginMode;
public LoginMode getLoginMode() {
return loginMode;
}
public void setLoginMode(LoginMode loginMode) {
this.loginMode = loginMode;
}
}
How can i convert the property of the configuration file (which is a String) into the corresponding enum value of LoginMode?
EDIT: i know how to get the enum value of a string input, but the issue is another one:
If i try this:
public class Environment {
private LoginMode loginMode;
public LoginMode getLoginMode() {
return loginMode;
}
public void setLoginMode(String loginMode) {
this.loginMode = LoginMode.valueOf(loginMode);
}
}
spring is complaining about getter and setter not having the same input and output type.
Bean property 'loginMode' is not writable or has an invalid setter method. Does the parameter type of the setter match the return type of the getter?
Spring automatically converts input Strings to the corresponding valueOf of the desired enum.
You can do that by
LoginMode.valueOf("someString");
LoginMode.valueOf(valueOfProperty);
EDIT:
Try using converter
http://docs.spring.io/spring/docs/3.0.0.RC2/reference/html/ch05s05.html
http://forum.spring.io/forum/spring-projects/web/83191-custom-enum-string-converters
EDIT2:
also check this:
How assign bean's property an Enum value in Spring config file?

NoUniqueBeanDefinitionException for Named classes

I am Using Spring 3.2.2 and was wondering if there was a way to inject beans by class type without explicitly giving them a string name. Ex:
#Named
public MyClass{
}
#Named
public MyOtherClass extends MyClass{
}
#Named
public class Foo{
public void blah(){
MyClass myClass = context.getBean(MyClass.class);
}
}
This will generate:
org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [MyClass] is defined: expected single matching bean but found 2: myClass,myOtherClass
Is there a way to say "Use the one that matches the class name exactly" without using String names?
In other words I don't want to do:
#Named("MyClass")...
#Named("MyOtherClass")...
MyClass myClass = context.getBean("MyClass");
Thanks!
This is what § 5.4.5 of Spring manual suggest whenever you encounter non-unique dependency bean definition:
Abandon autowiring in favor of explicit wiring.
Avoid autowiring for a bean definition by setting its autowire-candidate attributes to false as described in the next section.
Designate a single bean definition as the primary candidate by setting the primary attribute of its element to true.
If you are using Java 5 or later, implement the more fine-grained control available with annotation-based configuration, as described in Section 5.9, “Annotation-based container configuration”.
For the example, you could do something like:
#Named
public class Foo{
public void blah(){
MyClass myClass = getBean(MyClass.class);
}
private <T> T getBean(Class<T> type) {
return context.getBean(Introspector.decapitalize(type.getSimpleName()), type);
}
}
But this will not work when using #Inject or #Autowire.
To force strict class matching when autowiring, you could replace the default AutowireCandidateResolver on the BeanFactory with a BeanFactoryPostprocessor, but don't seem a good idea as #Resource or #Qualify can solve the NUBDE problem.
For example: (Not tested)
public class StrictClassAutowireCandidateResolver implements AutowireCandidateResolver {
#Override
public boolean isAutowireCandidate(BeanDefinitionHolder bdHolder, DependencyDescriptor descriptor) {
if (!bdHolder.getBeanDefinition().isAutowireCandidate()) {
return false;
}
if (descriptor == null) {
return true;
}
String className = null;
if (descriptor.getField() != null) {
className = descriptor.getField().getType().getName();
}
else if (descriptor.getMethodParameter() != null) {
className = descriptor.getMethodParameter().getParameterType().getName();
}
Class<?> clazz = null;
try {
clazz = Class.forName(className);
}
catch (Exception e) {
return false;
}
if (clazz.isInterface() || Modifier.isAbstract(clazz.getModifiers())) {
// have no chances to be strict, let BeanFactory to find implementations.
return true;
}
return bdHolder.getBeanDefinition().getBeanClassName().equals(className);
}
#Override
public Object getSuggestedValue(DependencyDescriptor descriptor) {
return null;
}
}
Try using #Component (Service, Repository, Controller) on your classes, and #Autowired when you're injecting a bean.
EDIT: my bad, I didn't read the question too well. The problem is that you're actually having 2 instances of MyClass (since MyOtherClass extends from MyClass). Hence there's no other way than giving the classes names, or you'll always end up with NoUniqueBeanDefinitionExceptions.

How can I validate a field as required depending on another field's value in SEAM?

I'm trying to create a simple custom validator for my project, and I can't seem to find a way of getting seam to validate things conditionally.
Here's what I've got:
A helper/backing bean (that is NOT an entity)
#RequiredIfSelected
public class AdSiteHelper {
private Date start;
private Date end;
private boolean selected;
/* getters and setters implied */
}
What I need is for "start" and "end" to be required if and only if selected is true.
I tried creating a custom validator at the TYPE target, but seam doesn't seem to want to pick it up and validate it. (Maybe because it's not an entity?)
here's the general idea of my custom annotation for starters:
#ValidatorClass(RequiredIfSelectedValidator.class)
#Target(ElementType.TYPE)
#Retention(RetentionPolicy.RUNTIME)
public #interface RequiredIfSelected {
String message();
}
public class RequiredIfSelectedValidator implements Validator<RequiredIfSelected>, Serializable {
public boolean isValid(Object value) {
AdSiteHelper ash = (AdSiteHelper) value;
return !ash.isSelected() || (ash.getStart() && ash.getEnd());
}
public void initialize(RequiredIfSelected parameters) { }
}
I had a similar problem covered by this post. If your Bean holding these values is always the same then you could just load the current instance of it into your Validator with
//Assuming you have the #Name annotation populated on your Bean and a Scope of CONVERSATION or higher
AdSiteHelper helper = (AdSiteHelper)Component.getInstance("adSiteHelper");
Also as you're using Seam your validators don't need to be so complex. You don't need an interface and it can be as simple as
#Name("requiredIfSelectedValidator")
#Validator
public class RequiredIfSelectedValidator implements javax.faces.validator.Validator {
public void validate(FacesContext context, UIComponent component, Object value) throws ValidatorException {
//do stuff
}
}

Categories