Bean property 'xxx' is not writable or has an invalid setter method - spring

I have spring web application. I have defined the controller bean which takes the bean of service as property. Also service bean takes the Dao. Dao is tested and working fine. Now the problem with service. Actually i'd make sure about the setters there !
so what is the problem ?
Controller Bean :
<bean id="listTypeController" class="me.web.servlet.controller.ListTypeController">
<property name="typeService" ref="typeService" />
</bean>
Service Bean :
<bean id="typeService"class="me.general.service.impl.TypeServiceImpl">
<property name="genericDao" ref="genericDao" />
<property name="typeDao" ref="typeDao" />
</bean>
Service class:
public class TypeServiceImpl implements TypeService {
private TypeDao typeDao;
private GenericDao genericDao;
public TypeDao getTypeDao() {
return typeDao;
}
public GenericDao getGenericDao() {
return genericDao;
}
public void setTypeDao(TypeDao typeDao) {
this.typeDao = typeDao;
}
public void setGenericDao(GenericDao genericDao) {
this.genericDao = genericDao;
}
}
List Controller:
public class ListTypeController {
public static final String SEARCH_TYPE_FORM_ATTRIBUTE_NAME = "SearchTypeForm";
private TypeService typeService;
#ModelAttributeSEARCH_TYPE_FORM_ATTRIBUTE_NAME)
public SearchTypeForm createForm() {
SearchTypeForm form = new SearchTypeForm();
form.setPageSize(SystemConfiguration.getCurrentConfiguration().getDefaultPageSize());
form.setActive(Boolean.TRUE);
return form;
}
#RequestMapping("/administration/types")
public String listTypes(#ModelAttribute(SEARCH_TYPE_FORM_ATTRIBUTE_NAME) SearchTypeForm form,
Model model) {
Page<Type> all = typeService.findTypes(form);
model.addAttribute("all", all);
return "/master/general/List";
}
public void setTypeServic(TypeService typeService) {
this.typeService = typeService;
}
}
The Error :
Invalid property 'typeService' of bean class
[me.web.servlet.controller.ListTypeController]:
Bean property 'typeService' is not writable or has an invalid setter method.
Does the parameter type of the setter match the return type of the getter?

ListTypeController doesn't have a property of the appropriate type to receive the typeService bean, or else the setter for that property is malformed. Note that if you have some proxying going on and your ListTypeController specifies the type as TypeServiceImpl, then it may be because you should be referring to the bean by its interface type, TypeService. A proxy of your typeService would be a TypeService, but not a TypeServiceImpl.
Update: Based on your new code: setTypeServic should be setTypeService, or else your property name is actually typeServic.

In my case i named my propery as: isMyProperty and is in prefix caused an issue. I had to change the name to myProperty.

In my case it was because I had correct setter and getter but each with different type.
My setter took String and parsed it to target enum type and my getter returned directly the enum.
For some reason Spring (v3) got confused.

Related

Add Bean Validation for a Converter

I would like to use validation for a converter bean, but I get the following error
HV000151: A method overriding another method must not redefine the parameter constraint configuration, but method StringToFooConverter#convert(String) redefines the configuration of Converter#convert(Object).
at org.hibernate.validator.internal.metadata.aggregated.rule.OverridingMethodMustNotAlterParameterConstraints.apply(OverridingMethodMustNotAlterParameterConstraints.java:24)
at org.hibernate.validator.internal.metadata.aggregated.ExecutableMetaData$Builder.assertCorrectnessOfConfiguration(ExecutableMetaData.java:462)
at org.hibernate.validator.internal.metadata.aggregated.ExecutableMetaData$Builder.build(ExecutableMetaData.java:380)
at org.hibernate.validator.internal.metadata.aggregated.BeanMetaDataBuilder$BuilderDelegate.build(BeanMetaDataBuilder.java:260)
at org.hibernate.validator.internal.metadata.aggregated.BeanMetaDataBuilder.build(BeanMetaDataBuilder.java:133)
at org.hibernate.validator.internal.metadata.BeanMetaDataManagerImpl.createBeanMetaData(BeanMetaDataManagerImpl.java:206)
at org.hibernate.validator.internal.metadata.BeanMetaDataManagerImpl.getBeanMetaData(BeanMetaDataManagerImpl.java:165)
at org.hibernate.validator.internal.engine.ValidatorImpl.validateParameters(ValidatorImpl.java:267)
at org.hibernate.validator.internal.engine.ValidatorImpl.validateParameters(ValidatorImpl.java:235)
Converter
#Validated
public class StringToFooConverter implements Converter<String, Foo> {
#Override
public Foo convert( #NotNull final String source ) {
return new Foo( source );
}
}
Config
#Bean
public StringToFooConverter stringToFooConverter() {
return new StringToFooConverter();
}
What is wrong?
EDIT:
Add a example and what iam tried.
https://github.com/MelleD/spring-bean-validation-example
Interface and DTO is generated by open api generator. So currently not changeable.

Bean property 'iUserGeneratorInterface' is not writable or has an invalid setter method

I have a project structure as follows
[1]: http://i.stack.imgur.com/T1jvh.png
I have a class and interface defined in create-user
UserGeneratorInterface
package com.credit.userGenerator;
public interface UserGeneratorInterface {
public String userIdGenerator();
}
RandomUserGenerator.java
public class RandomUserGenerator implements UserGeneratorInterface {
public static enum Mode {
ALPHA, ALPHANUMERIC, NUMERIC
}
public static String generateRandomString(int length, Mode mode) throws Exception {
code logic
}
public String userIdGenerator(){
code logic
}
}
I have defined application context in da-web and wan to get service of RandomUserGenerator.java
public class ApplicationSignManager implements IApplicationSignInterface {
public UserGeneratorInterface iUserGeneratorInterface;
public UserGeneratorInterface getiUserGeneratorInterface() {
return iUserGeneratorInterface;
}
public void setiUserGeneratorInterface(
UserGeneratorInterface iUserGeneratorInterface) {
this.iUserGeneratorInterface = iUserGeneratorInterface;
}
}
AppContext.xml
<bean id="userGenerator" class="com.credit.userGenerator.RandomUserGenerator" ></bean>
<bean id="appSign" class="com.*****.service.ApplicationSignManager">
<description>List of Dao in ApplicationLogin Manager</description>
<property name="userGeneratorInterface" ref="userGenerator"/>
</bean>
But I am getting the following exception
Bean property 'iUserGeneratorInterface' is not writable or has an invalid setter method. Does the parameter type of the setter match the return type of the getter?
As noticed in the comments, use setIUserGeneratorInterface() and getIUserGeneratorInterface() with capital 'I'.
Use 'property name="iUserGeneratorInterface" ref="userGenerator"' - note the leading 'i'.
Note that it is always advisable to use well-established practices when naming your classes and fields. In your case naming 'UserGeneratorInterface' simply 'UserGenerator' and naming the field 'iUserGeneratorInterface' simply 'userGenerator' would make more sense. Note also that you have declared this field public (although this has nothing to do with the errors).
Your bean id="userGenerator"
Use this "userGenerator" like (public UserGeneratorInterface userGenerator;) as same as the variable name.
And create getter, setter for this variable
then try

How to choose spring configuration in runtime based on a tenant?

I would like to be able to choose specific Spring (or Grails) context configuration based on the tenant that user belongs to in runtime. Let's say I use Spring Security and I retrieve tenantId during login.
Imagine now I have a two tenants and they pay different commission. How to inject specific service into a controller without too much plumbing? Here are two different contexts. So, I should inject different ExchangeService based on tenant.
#Configuration
public class FooTenant{
#Bean
public ExchangeService bar() {
return new ZeroCommisionExchangeService ();
}
}
#Configuration
public class BarTenant{
#Bean
public ExchangeService bar() {
return new StandardCommisionExchangeService ();
}
}
Edit:
I am aware I can obtain reference to Spring context and ask for service "manually", but I am looking for a more generic solution where this problematic is solved by IoC framework.
A couple of years ago we needed somthing like this but only for DataSources and ViewResolvers. We developed a solution using spring' TargetSource solution. (Initially we used a HotswappableTargetSource but that wasn't adequate for our use-case.
The code we developed is availabe here in the multi-tenant directory.
It is fully configurable and flexible.
Basically what you do is you configura a ContextSwappableTargetSource and tell it what type of interface/class it needs to return.
<bean id="yourTentantBasedServiceId" class="biz.deinum.multitenant.aop.target.ContextSwappableTargetSource">
<constructor-arg value="ExchangeService" />
</bean>
The default is to lookup beans in the ApplicationContext based on the tenantId (see the BeanFactoryTargetRegistry for this). However you can specify one or more of those (we used a JndiLookupTargetRegistry to dynamically lookup datasource, which allowed use to add tenants on the fly without restarting the application).
If you explicitly configure a BeanFactoryTargetRegistry you can add a prefix and suffix.
<bean id="exchangeService" class="biz.deinum.multitenant.aop.target.ContextSwappableTargetSource">
<constructor-arg value="ExchangeService" />
<property name="targetRegistry>
<bean class="biz.deinum.multitenant.aop.target.registry.impl.BeanFactoryTargetRegistry">
<property suffix="ExchangeService"/>
</bean>
</property>
</bean>
Now for foo it would lookup a bean named fooExchangeService and for bar barExchangeService.
The tenantId is stored in a ThreadLocal which is wrapped inside the ContextHolder. You need to find a way to fill and clear this thread local (in general a servlet Filter does that trick.
In your code you can now simply use the interface ExchangeService and at runtime based on the tenantId the correct implemenation will be looked up.
Also see http://mdeinum.wordpress.com/2007/01/05/one-application-per-client-database/
Assuming you have different services already defined, you can get their bean from the context and use it. In my example, all the services have implementation of serviceMethod and based on some criteria pick your proper service. The only thing I am not sure is how Multitenancy might impact this.
import org.springframework.context.ApplicationContext
class ServiceManagerController {
def serviceManager
def index() {
ApplicationContext ctx = grails.util.Holders.grailsApplication.mainContext
serviceManager = ctx.getBean(params.serviceName); //firstService or secondService
render serviceManager.serviceMethod()
}
}
FirstService
class FirstService {
def serviceMethod() {
return "first"
}
}
SecondService:
class SecondService {
def serviceMethod() {
return "second"
}
}
While it is possible to swap beans instantiated in a spring context at runtime (HotswappableTargetSource), it is not meant for use cases such as yours.
Remember there is one Spring Context for your application, all threads use the same instances (in most cases), this implies when you swap out a bean implementation, you are affectively doing this for all your application's users. To prevent this, you run into issues of ensuring Thread Safety, employing Thread Locals, as listed in another answer.
While it is possible to continue this approach and arrive at an implementation that gets the job done, it would definitely be a very contrived way of solving this problem.
You should take a step back and look at your problem in a more wholesome, system wide design point of view. Bust out your patterns books and look at how this can be resolved, regardless of whether you use Spring or an other framework. Service Locator, Factory bean etc described in some of the answers above is a step in the correct direction.
Your Use Case is pretty common for multi-tenant applications. You need to narrow down things that are likely to change based on a tenantId versus things that are constant across.
For instance as mentioned in the question, each Tenant might have a different commission amount or even different algorithm for commission calculation. A simple solution to this would be to implement a CommissionCalculationService which accepts a tenantId, and any other domain object based on which commission is to be calculated, I would imagine this would be something like Order or Sale, whatever makes sense in your application.
You now need a CommissionServiceFactory or a ServiceLocator which will contain tenant specific implementations of the CommissionCalculationService. The Service Locator is instantiated when the Spring context loads, and is injected with implementation classes also at application startup.
When you want to calculate commission for a tenant, you basically obtain the tenantId from the user's login, pass the tenant id to your service locator, based on the tenantId passed, the service locator returns the appropriate instance of a Service Implementation. In your calling class, use this instance to calculate the commission for the tenant.
Another pattern to consider is the Strategy Pattern, or even Template Pattern.
Bottom line, even if you want tenant specific logic implemented cleanly, don't thing about changing the beans loaded in the context. Have classes in your context that can handle all your tenant specific logic. Rely on design patterns to use the correct bean from the context based on the tenant id.
I apologize if the answer was a little verbose, I felt it was needed to explain why I think updating beans in a loaded Spring Context is not the appropriate solution.
I use the following code:
public class ConfigurableProxyFactoryBean implements FactoryBean<Object>, BeanNameAware {
#Autowired
private ApplicationContextProvider applicationContextProvider;
private Class<?> proxyType;
private String beanName;
private Object object;
private Object fallbackObject;
private Object monitor = new Object();
private ConfigurableProxy proxy;
public ConfigurableProxyFactoryBean(Class<?> proxyType) {
this.proxyType = proxyType;
}
public Object getFallbackObject() {
return fallbackObject;
}
public void setFallbackObject(Object fallbackObject) {
synchronized (monitor) {
this.fallbackObject = fallbackObject;
if (proxy != null) {
proxy.setFallbackObject(fallbackObject);
}
}
}
#Override
public void setBeanName(String name) {
beanName = name;
}
#Override
public Object getObject() throws Exception {
synchronized (monitor) {
if (object == null) {
#SuppressWarnings("unchecked")
Class<Object> type = (Class<Object>)proxyType;
proxy = new ConfigurableProxy(applicationContextProvider, beanName);
proxy.setFallbackObject(fallbackObject);
object = Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),
new Class<?>[] { type }, proxy);
}
return object;
}
}
#Override
public Class<?> getObjectType() {
return proxyType;
}
#Override
public boolean isSingleton() {
return true;
}
}
class ConfigurableProxy implements InvocationHandler {
public ConfigurableProxy(ApplicationContextProvider appContextProvider, String beanName) {
this.appContextProvider = appContextProvider;
this.beanName = beanName;
}
private ApplicationContextProvider appContextProvider;
private String beanName;
private Object fallbackObject;
#Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
ApplicationContext appContext = appContextProvider.getApplicationContext();
String name = "$&&#" + beanName;
Object bean = appContext.containsBean(name) ? appContext.getBean(name) : fallbackObject;
return method.invoke(bean, args);
}
public void setFallbackObject(Object fallbackObject) {
this.fallbackObject = fallbackObject;
}
}
ApplicationContextProvider has implementation, that chooses ApplicationContext according to current tennant.
In XML configuration it is used like this:
<bean class="my.package.infrastructure.ConfigurableProxyFactoryBean" name="beanName">
<constructor-arg>
<value type="java.lang.Class">my.package.model.ServiceInterface</value>
</constructor-arg>
<property name="fallbackObject">
<bean class="my.package.service.DefaultServiceImplementation"/>
</property>
</bean>
And in tennant configuration that way:
<bean class="my.package.service.ServiceImplementationA" name="$&&#beanName"/>
To inject this service somewhere you just write:
public class MyController {
#Autowired
private ServiceInterface service;
}
Also you are to implement ApplicationContextProvider, I won't share mine. It is not very hard to implement. For example, your implementation can just store context in ThreadLocal. And you create your own ServletContextListener, which for every query gets the current tennant and stores it into your ApplicationContextProvider implementation.
The new tenant scope and a servicelocator can helps
Tenant scope will guarantee than service is created one time for a tenant
Sample code:
<bean class="org.springframework.beans.factory.config.CustomScopeConfigurer">
<property name="scopes">
<map>
<entry key="tenant" value="foo.TenantScope"/>
</map>
</property>
</bean>
<bean id="service" class="foo.Service" factory-bean="tenantServiceLocator" factory-method="createInstance" scope="tenant"/>
<bean id="fooService" class="FooService">
<bean id="barService" class="BarService">
<bean id="tenantServiceLocator" class="foo.TenantServiceLocator">
<property name="services">
<map>
<entry key="foo" value-ref="fooService"/>
<entry key="bar" value-ref="barService"/>
</map>
</property>
</bean>
TenantServiceLocator should know the user tenantId
public class TenantServiceLocator {
private Map<String, Service> services;
public String getTenantId() {
return "foo"; // get it from user in session
}
public Map<String, Service> getServices() {
return services;
}
public void setServices(Map<String, Service> services) {
this.services = services;
}
public Service createInstance(){
return services.get(tenantId);
}
}
public class FooController{
#Autowired
private Service service;
}
A sample TenantScope implementation
public class TenantScope implements Scope {
private static Map<String, Map<String, Object>> scopeMap = new HashMap<String, Map<String, Object>>();
#Override
public Object get(String name, ObjectFactory<?> objectFactory) {
Map<String, Object> scope = getTenantScope(getTenantId());
Object object = scope.get(name);
if(object == null){
object = objectFactory.getObject();
scope.put(name, object);
}
return object;
}
private Map<String, Object> getTenantScope(String tenantId) {
if (!scopeMap.containsKey(tenantId)) {
scopeMap.put(tenantId, new HashMap<String, Object>());
}
return scopeMap.get(tenantId);
}
private String getTenantId() {
return "foo"; // load you tenantId
}
#Override
public Object remove(String name) {
Map<String, Object> scope = getTenantScope(getTenantId());
return scope.remove(name);
}
#Override
public void registerDestructionCallback(String name, Runnable callback) {
}
#Override
public Object resolveContextualObject(String key) {
return null;
}
#Override
public String getConversationId() {
return null;
}
}
Transforming my comment in an answer, one possible solution is to create a spring factory bean, that receive all he needs to decide which service needs to be returned when creating the instance.
Translating to Grails:
public interface ChoosableServiceIntf {
String getName();
}
class NormalService implements ChoosableServiceIntf {
public String getName() {
return getClass().name;
}
}
class ExtendedService implements ChoosableServiceIntf {
public String getName() {
return getClass().name
}
}
class ChoosableServiceFactory {
static ChoosableServiceIntf getInstance(String decisionParam) {
if(decisionParam == 'X') {
return applicationContext.getBean('extendedService')
}
return applicationContext.getBean('normalService')
}
static ApplicationContext getApplicationContext() {
return Holders.grailsApplication.mainContext
}
}
Here we have two services and ChoosableServiceFactory is responsible to know witch is the correct one.
Then you will need to use the method ApplicationContext#getBean(String, Object[]) to return the correct instance and will also make the factory prototyped scope because of the runtime params.
A controller to test it:
class MyController {
def grailsApplication
def index() {
ChoosableServiceIntf service = grailsApplication.mainContext.getBean('choosableServiceFactory', ["X"] as Object[])
ChoosableServiceIntf serviceNormal = grailsApplication.mainContext.getBean('choosableServiceFactory', ["N"] as Object[])
render text: "#1 - ${service.class.name} , #2 - ${serviceNormal.class.name}"
}
}
This will print #1 - dummy.ExtendedService , #2 - dummy.NormalService
The declaration of the beans will be:
choosableServiceFactory(ChoosableServiceFactory) { bean ->
bean.scope = 'prototype'
bean.factoryMethod = 'getInstance'
}
normalService(NormalService)
extendedService(ExtendedService)

Inject properties via annotation

I am new for spring security. I've seen many posts on how to inject values via annotation from external property file. I've tried many ways, but I always end up with java.lang.IllegalArgumentException: Could not resolve placeholder 'val.id' exception.
Can you provide me some tips how to handle this exception please?
My java class is the following one:
#Controller
public class Employee {
#Value("${val.id}")
public String valId;
public String getValId() {
return valId;
}
public void setValId(String valId) {
this.valId = valId;
}
My property file is called val.properties which is located under WEB-INF, and its content is
val.id=xyz
I put the following in my main context bean.
<context:property-placeholder location="/WEB-INF/*.properties" />
<bean id="valProp" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"
p:location="/WEB-INF/val.properties"/>
A continuous question:
The injecting values from properties file to annotated beans works fine as I accepted the answer above. However, I cannot able to inject it to #PreAuthorize(...) annotation by following the same procedure.
Assume I want to secure a method called 'update'. This method is allowed if and only if valId is equal to empId. values of valId and empId are initialized in the val.properties file.
my java bean is:
public class Employee {
public String valId;
public String empId;
public String getValId() {
return valId;
}
public void setValId(String valId) {
this.valId = valId;
}
public String getEmpId() {
return empId;
}
public void setEmpId(String empId) {
this.empId = empId;
}
}
my property file contains:
val.id=nn
emp.id=nn
I have the place holder configuration in my main context file:
<context:property-placeholder location="/WEB-INF/*.properties" />
<bean id="valProp" class="org.springframework.beans.factory.config.PropertiesFactoryBean"
p:location="/WEB-INF/val.properties"/>
My PreAuthorize annotation (method security) is:
#PreAuthorize("(#{valProp['val.id']} == #{valProp['emp.id']})")
public boolean update(){
//if accessable
return true;
}
But the expression #{valProp['val.id']} == #{valProp['emp.id']} is not evaluated.
Did I do any mistake to inject values? It was worked when I annotate member variables, but it doesn't work here. Any idea please? Thanks in advance.
try to consider the following
1). change your annotation to:
#Value("#{valProp['val.id']}")
2). Replace PropertyPlaceholderConfigurer by PropertiesFactoryBean.
Hope this will resolve the exception.
The reason why the exception is thrown is, because the property placeholder by default throws an exception when a values cannot be resolved.
Furthermore you have two property placeholders, via which probably not all values can be resolved.
You can change this behaviour via setting the ignore-unresolvable property:
<context:property-placeholder location="/WEB-INF/*.properties" ignore-unresolvable="true" />
<bean id="valProp" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"
p:location="/WEB-INF/val.properties" p:ignoreUnresolvablePlaceholders="true" />
Note however that b< turning off this feature typos in a property file will not be detected.

Defined bean to take enum construtor-arg

A connection pool class used for all the data source connections. It has a static enum to indicate type of connection.
class ConnectionPool {
public static enum Type {
t1,
t2,
t3;
}
…
}
Another class does not have default contractor, the constructor takes the Type as contractor argument
class Update {
public Update(Type type) {
this.type = type;
}
...
}
In applicationContext.xml, defined a bean
<bean id="update" class="package.Update">
<contructor-arg type="package.ConnectionPool.Type">
<value>Type.t1</value>
</contructor-arg>
</bean>
But I got
Error creating bean with name 'update' defined in class path resource [applicationContext.xml]: Unsatisfied dependency expressed through constructor argument with index 0 of type [package.ConnectionPools$PoolType]: Ambiguous constructor argument types - did you specify the correct bean references as constructor arguments?
This should work:
<bean id="update" class="package.Update">
<contructor-arg type="package.ConnectionPool.Type">
<value>t1</value>
</contructor-arg>
</bean>
or even:
<bean id="update" class="package.Update">
<contructor-arg type="package.ConnectionPool.Type" value="t1"/>
</bean>
or my favorite:
#Configuration
public class Config {
#Bean
public Update update() {
return new Update(t1);
}
}

Resources