Announcement Announcement Module
Collapse
No announcement yet.
Changing bean properties programmatically Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Changing bean properties programmatically

    Hi all
    I'm using this environment:
    • spring 3.1
    • jvm 6

    I'ld like to valorize some bean properties by quirying the DB. For example let's image this code:

    Code:
    import stuffs....
    @Service("mySimpleSvc")
    public class MySvc{
    
    @MyCustomAnnotation
    protected String valorizeFromDb;
    
    protected String notValorizeFromDb;
    }
    What I would like is to te able in valorizing the property valorizeFromDb after bean creation and by querying the database
    In order to do it i was thinking to use a "BeanFactoryPostProcessor" way but in this case I can't autowire spring beans.
    I was thinking in something like this:
    Code:
    @Service("valorizeFromDbSvc")
    public class ConfigurationService implements BeanFactoryPostProcessor {
    	private MyDao myDao;
    	@Autowired
    	public void setParamCfgMgrDao(MyDao dao){
    		this.myDao = dao;
    	}
    	private void checkObjectFields(MyInterface object) throws IllegalArgumentException, IllegalAccessException, MktiDbException, InvocationTargetException{
    		Field[] fields = object.getClass().getDeclaredFields();
    		for (int i = 0; i < fields.length; i++) {
    			Field field = fields[i];
    			if(field.isAnnotationPresent(MyCustomAnnotation.class)){
    				if (field.isAnnotationPresent(MyCustomAnnotation.class)) {
    					MyCustomAnnotation annotation = field.getAnnotation(MyCustomAnnotation.class);
    					Object value = getNotNullParamConfiguration(field.getName(), field.getType(), annotation);
    //This is commons beans BeanUtils class
    					BeanUtils.setProperty(object, field.getName(), value);
    				}
    			}
    		}
    	}
    	@SuppressWarnings("unchecked")
    	protected <T> T getNotNullParamConfiguration(String paramName, Class<T> returnType, MyCustomAnnotation annotation) throws MktiDbException {
    		T result = null;
    		if (paramName != null && !paramName.isEmpty()) {
    			String value = myDao.getValueConfiguration(paramName);
    			try {
    				if (Number.class.isAssignableFrom(returnType)) {
    					result = (T) NumberUtils.parseNumber(value.trim(), (Class<Number>) returnType);
    				} else {
    					return (T) value;
    				}
    			} catch (Exception e) {
    e.printStackTrace();
    			}
    		}
    		return result;
    	}
    	@Override
    	public void postProcessBeanFactory(ConfigurableListableBeanFactory clbf) throws BeansException {
    		try{
    			Map<String, MyInterface> beans = clbf.getBeansOfType(MyInterface.class);			
    			if(beans != null && !beans.isEmpty()){
    				Collection<MyInterface> valori = beans.values();
    				for (IInViMallMktIntelligence bean : valori) {
    					checkObjectFields(bean);
    				}
    			}
    		} catch (Exception e) {
    			String message = "Error; error message: "+e.getMessage();
    			logger.fatal(message, e);
    			throw new IllegalStateException(message);
    		}
    	}
    
    }
    But in this case, obviously, i can't autowire the DAO object.
    Is there any other way in order to do it?

    Thank you
    Angelo

  • #2
    Do you really need a custom annotation, why not simply integrate with the new PropertySource abstraction, make one that retrieves values from the database and simply use a @Value annotation. That way spring is doing all the hard work.

    Comment


    • #3
      Hello Marten
      First of all thank you for answering to me.
      With regards to your suggestion I didn't use the PropertySource basically for two reason:
      1. I didn't know it
      2. I must admit I was too generic in my post

      I'll try to summarize what I wanted to do: I need to load some configuration data from DB but at the same time if the choosen configuration parameter is not present in the DB i need to insert it by setting some default values.
      Finally I need to do a query on DB and if this query doesn't give me a result i need to valorize properties with default values and then store the new configuration parameter in the DB.
      I was able in doing it by using the org.springframework.beans.factory.config.BeanPostP rocessor process...but since I like doing things in the best way I'ld like to have some feedback regarding if I did it in the most spring oriented way
      What I did is to create the following class:
      Code:
      //Package and import stuffs
      
      @Service("customParamConfigurationService")
      public class ParamConfigurationService implements ApplicationContextAware, BeanPostProcessor {
      
      	private IParamConfigurationManagerDao paramConfigurationManagerDao;
      	private List<String> scopedBeanNames;
      	@Autowired
      	public void setParamCfgMgrDao(IParamConfigurationManagerDao dao){
      
      		this.paramConfigurationManagerDao = dao;
      	}
      
      	@Override
      	public void setApplicationContext(ApplicationContext ctx) throws BeansException {
      
      		scopedBeanNames = Arrays.asList(ctx.getBeanNamesForType(MyCustomInterface.class));
      	}
      
      	@SuppressWarnings("unchecked")
      	protected <T> T getNotNullParamConfiguration(String paramName, Class<T> returnType, CustomAnnotation annotation) {
      
      		T result = null;
      		if (paramName != null && !paramName.isEmpty()) {
      			try {
      				String value = paramConfigurationManagerDao.getValueConfiguration(paramName);
      				if ((value == null || value.isEmpty()) && annotation.mandatory()) {
      					value = annotation.defaultValue();
      					ConfigParamDTO entity = new ConfigParamDTO();
      					entity.setChiave(paramName);
      					entity.setValore(annotation.defaultValue());
      					entity.setDescrizione(annotation.defaultDescription());
      					if(logger.isWarnEnabled()){
      
      						logger.warn("Non e' stato trovato alcun valore per " + paramName+"; inserisco il record e valorizzo value con il valore di default preso dalle annotation; record da salvare: "+entity);
      					}
      					paramConfigurationManagerDao.storeParam(entity);
      				}
      
      				if (Number.class.isAssignableFrom(returnType)) {
      					result = (T) NumberUtils.parseNumber(value.trim(), (Class<Number>) returnType);
      				} else {
      					return (T) value;
      				}
      			} catch (Exception e) {
      				throw new IllegalArgumentException("Si Ŕ verificato un errore durante la conversione del parametro " + paramName + " nel tipo " + returnType.getName());
      			}
      		}
      
      		return result;
      	}
      	@Override
      	public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
      
      		return bean;
      	}
      	@Override
      	public Object postProcessBeforeInitialization(final Object bean, String beanName) throws BeansException {
      		try{
      			
      			if(scopedBeanNames.contains(beanName)){
      
      				ReflectionUtils.doWithFields(bean.getClass(), new ReflectionUtils.FieldCallback() {
      
      					@Override
      					public void doWith(Field field) throws IllegalArgumentException, IllegalAccessException {
      						if(field.isAnnotationPresent(CustomAnnotation.class)){
      
      							if (field.isAnnotationPresent(CustomAnnotation.class)) {
      								CustomAnnotation annotation = field.getAnnotation(CustomAnnotation.class);
      								Object value = getNotNullParamConfiguration(field.getName(), field.getType(), annotation);
      								if(!field.isAccessible()){
      									field.setAccessible(true);
      								}
      								field.set(bean, value);
      							}
      						}
      
      					}
      				});
      			}
      			return bean;
      		}catch (Exception e) {
      
      			String message = "Errore durante la pre volarizzazione delle proprietÓ; messaggio errore "+e.getMessage();
      			logger.fatal(message, e);
      			throw new FatalBeanException(message);
      		}
      	}
      }
      According to you....is this the best way in order to do what I needed?
      Thank you

      Angelo

      Comment


      • #4
        According to you....is this the best way in order to do what I needed?
        No. Way to complex (IMHO) I would simply create a factory bean which loads properties from the database (implementations are available on the forum). The @Value annotation can also provide a default value (check the reference guide for the syntax).

        Comment


        • #5
          Originally posted by Marten Deinum View Post
          I would simply create a factory bean which loads properties from the database (implementations are available on the forum). The @Value annotation can also provide a default value (check the reference guide for the syntax).
          Hi
          Thank you for answering.
          I'll give a look at what you suggested
          Cheers,
          Angelo

          Comment

          Working...
          X