Results 1 to 5 of 5

Thread: Changing bean properties programmatically

  1. #1
    Join Date
    May 2009
    Posts
    23

    Default 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. #2
    Join Date
    Jun 2006
    Location
    The Netherlands
    Posts
    13,632

    Default

    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.
    Marten Deinum
    Java Consultant / Pragmatist / Open Source Enthousiast / Author


    Pro Spring MVC: With Web Flow
    Conspect

    Have you read the reference guide.
    Use the [ code ] tags, young padawan

  3. #3
    Join Date
    May 2009
    Posts
    23

    Default

    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

  4. #4
    Join Date
    Jun 2006
    Location
    The Netherlands
    Posts
    13,632

    Default

    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).
    Marten Deinum
    Java Consultant / Pragmatist / Open Source Enthousiast / Author


    Pro Spring MVC: With Web Flow
    Conspect

    Have you read the reference guide.
    Use the [ code ] tags, young padawan

  5. #5
    Join Date
    May 2009
    Posts
    23

    Default

    Quote 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

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •