-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 18 posts ]  Go to page 1, 2  Next
Author Message
 Post subject: How to refresh ResourceBundle dynamically without stoping???
PostPosted: Tue Jun 01, 2010 2:39 am 
Newbie

Joined: Tue Jun 01, 2010 2:20 am
Posts: 10
Hi,

I am new to JSF and in our application we are using the Hibernate validators.
Our application is dynamically write the ValidatorMessages.properties at /WEB-INF/classes location at startup.

I am able to rewrite ValidatorMessages.properties at /WEB-INF/classes based on database changes.
But how to reload ValidatorMessages.properties ResourceBundle without stoping the server?

I have tried the following code but doesn't work

HibernateValidatorConfiguration configuration = Validation.byProvider(HibernateValidator.class).configure();
ResourceBundleLocator defaultResourceBundleLocator = configuration.getDefaultResourceBundleLocator();
ResourceBundleLocator myResourceBundleLocator = new MessagesResourceBundleLocator ();
configuration.messageInterpolator(new ResourceBundleMessageInterpolator(myResourceBundleLocator));

public class MessagesResourceBundleLocator implements ResourceBundleLocator
{
@Override
public ResourceBundle getResourceBundle(Locale locale) {
ResourceBundle.clearCache(Thread.currentThread().getContextClassLoader());
return ResourceBundle.getBundle("ValidationMessages");

}
}

Any soulution? thanks in advance.


Last edited by msreddy on Mon Jun 28, 2010 12:44 am, edited 1 time in total.

Top
 Profile  
 
 Post subject: Re: How to refresh ResourceBundle dynamically without stoping???
PostPosted: Tue Jun 01, 2010 5:03 am 
Hibernate Team
Hibernate Team

Joined: Thu Apr 05, 2007 5:52 am
Posts: 1689
Location: Sweden
I don't think your custom ResourceBundleLocator will work in this case. One problem could be the context class loader. It is not guaranteed that the bundles are loaded via this classloader. More importantly though is that the default message interpolator of Hibernate Validator - ResourceBundleMessageInterpolator - applies some own caching.

I think what you really want is to write your own MessageInterpolator. This interpolator could then even get it's messages directly from the database. This way you would not have to write the properties file to disk.

--Hardy


Top
 Profile  
 
 Post subject: Re: How to refresh ResourceBundle dynamically without stoping???
PostPosted: Tue Jun 01, 2010 8:07 pm 
Newbie

Joined: Tue Jun 01, 2010 2:20 am
Posts: 10
hardy.ferentschik wrote:
I don't think your custom ResourceBundleLocator will work in this case. One problem could be the context class loader. It is not guaranteed that the bundles are loaded via this classloader. More importantly though is that the default message interpolator of Hibernate Validator - ResourceBundleMessageInterpolator - applies some own caching.

I think what you really want is to write your own MessageInterpolator. This interpolator could then even get it's messages directly from the database. This way you would not have to write the properties file to disk.

--Hardy


Hi Hardy,

Thank for your response.

So there is no way to dynamically load resource bundle.
Currently we are using hibernate-validator-4.0.2.GA.jar
Is there any possiblility to load resourceBundle dynamically by using new hibernate-validator-4..0.Beta1

Thank you


Top
 Profile  
 
 Post subject: Re: How to refresh ResourceBundle dynamically without stoping???
PostPosted: Wed Jun 02, 2010 3:54 am 
Hibernate Team
Hibernate Team

Joined: Thu Apr 05, 2007 5:52 am
Posts: 1689
Location: Sweden
The beta 1 version of HV 4.1 will not help you in this case. I created HV-330. It will probably be part of beta 2. If not it will be part of the CR/Final release.

--Hardy


Top
 Profile  
 
 Post subject: Re: How to refresh ResourceBundle dynamically without stoping???
PostPosted: Thu Jun 03, 2010 11:15 pm 
Newbie

Joined: Tue Jun 01, 2010 2:20 am
Posts: 10
hardy.ferentschik wrote:
The beta 1 version of HV 4.1 will not help you in this case. I created HV-330. It will probably be part of beta 2. If not it will be part of the CR/Final release.

--Hardy


Hi Hardy,

Is it possible to reload ResourceBundle at Runtime with hibernate-validator-4.1.0.Beta2.jar?
I tried with the following code, but it doesn't help me.

HibernateValidatorConfiguration configuration = Validation.byProvider(HibernateValidator.class).configure();
ResourceBundleLocator defaultResourceBundleLocator = configuration.getDefaultResourceBundleLocator();
ResourceBundleLocator myResourceBundleLocator = new MessagesResourceBundleLocator ();
configuration.messageInterpolator(new ResourceBundleMessageInterpolator(myResourceBundleLocator, false));

Is there any performance issues if I disable the cache? Will the ResourceBundle loads everytime?

Is ResourceBundle caching at ResourceBundleMessageInterpolator OR CachingResourceBundleLocator.

In Debug mode I forced cacheMessages=false and updated my ValidatorMessages.properties but it still picking the old message from ValidatorMessages.properties.

Thank you


Last edited by msreddy on Fri Jun 04, 2010 12:37 am, edited 1 time in total.

Top
 Profile  
 
 Post subject: Re: How to refresh ResourceBundle dynamically without stoping???
PostPosted: Fri Jun 04, 2010 12:35 am 
Newbie

Joined: Tue Jun 01, 2010 2:20 am
Posts: 10
edited in previous question


Top
 Profile  
 
 Post subject: Re: How to refresh ResourceBundle dynamically without stoping???
PostPosted: Fri Jun 04, 2010 5:04 am 
Hibernate Team
Hibernate Team

Joined: Thu Apr 05, 2007 5:52 am
Posts: 1689
Location: Sweden
Quote:
Is it possible to reload ResourceBundle at Runtime with hibernate-validator-4.1.0.Beta2.jar?

Right, there is another problem I didn't see initially. There are actually two levels of caching. CachingResourceBundleLocator which is caching the actual resource bundles. On top of this ResourceBundleMessageInterpolator cached some interpolation steps. The latter was addressed in HV-330. I created HV-332 for the former problem.

Quote:
Is there any performance issues if I disable the cache? Will the ResourceBundle loads everytime?

Of course there are some more steps to take if caching is disabled, but I don't think it will have any noticeable impact.

--Hardy


Top
 Profile  
 
 Post subject: Re: How to refresh ResourceBundle dynamically without stoping???
PostPosted: Fri Jun 18, 2010 12:12 am 
Newbie

Joined: Tue Jun 01, 2010 2:20 am
Posts: 10
Quote:
Right, there is another problem I didn't see initially. There are actually two levels of caching. CachingResourceBundleLocator which is caching the actual resource bundles. On top of this ResourceBundleMessageInterpolator cached some interpolation steps. The latter was addressed in HV-330. I created HV-332 for the former problem.


Hi Hardy

hibernate-validator-4.1.0.CR1.jar doesn't help me to reload the Resource bundle dynamically.

Could you please let me know whether dynamic reloading of resource bundle problem fixed in hibernate-validator-4.1.0.CR1.jar?

Java6 ResourceBundle class introduced 2 new methods clearCache() & clearCache(ClassLoader loader) which clears the cache.
With the following code I am able to retrieve the updated message.
ResourceBundle.clearCache(Thread.currentThread().getContextClassLoader());
ResourceBundle bundle = ResourceBundle.getBundle("ValidationMessages");
System.out.println(bundle.getString("sc.messages.E050SC"));

But in our case the hibernate-validator is caching the ResourceBundle. Please let me know is there any solution to clear Resourcebundle cache from hibernate-validator.

Thank you


Top
 Profile  
 
 Post subject: Re: How to refresh ResourceBundle dynamically without stoping???
PostPosted: Fri Jun 18, 2010 6:33 am 
Hibernate Team
Hibernate Team

Joined: Thu Apr 05, 2007 5:52 am
Posts: 1689
Location: Sweden
Hi,

I cannot see anything anymore in the HV code which would prevent your attempt to dynamically reload the bundles. I assume you do something like this to create the message interpolator:

Code:
new ResourceBundleMessageInterpolator(myResourceBundleLocator, false)


If the 'cacheMessages' flag is set to false the interpolator will always ask myResourceBundleLocator for the resource bundle - see ResourceBundleMessageInterpolator.

Does your code for reloading the bundle works as unit test or does it work in the running web application. Maybe you can isolate a testcase I can run. I don't see where the latest version of HV should still be caching the bundles.

--Hardy


Top
 Profile  
 
 Post subject: Re: How to refresh ResourceBundle dynamically without stoping???
PostPosted: Mon Jun 21, 2010 12:06 am 
Newbie

Joined: Tue Jun 01, 2010 2:20 am
Posts: 10
hardy.ferentschik wrote:
Does your code for reloading the bundle works as unit test or does it work in the running web application. Maybe you can isolate a testcase I can run. I don't see where the latest version of HV should still be caching the bundles.


Hi Hardy,

Its reloading the Resource bundle, when ResourceBundleMessageInterpolator cacheMessages=false. I have tested this by changing cacheMessages=false in debug mode.

But not able to set cacheMessages=false programatically.
<p>
Here is my code:

HibernateValidatorConfiguration configuration = Validation.byProvider(HibernateValidator.class).configure();
ResourceBundleLocator defaultResourceBundleLocator = configure.getDefaultResourceBundleLocator();
ResourceBundleLocator myResourceBundleLocator = new MyCustomResourceBundleLocator(defaultResourceBundleLocator);
configuration.messageInterpolator(new ResourceBundleMessageInterpolator(myResourceBundleLocator, false));

//MyCustomResourceBundleLocator
public class MyCustomResourceBundleLocator implements ResourceBundleLocator
{

private PlatformResourceBundleLocator delegate;

MyCustomResourceBundleLocator(ResourceBundleLocator locator)
{
this.delegate = (PlatformResourceBundleLocator) locator;
}

@Override
public ResourceBundle getResourceBundle(Locale locale) {
return ResourceBundle.getBundle("ValidationMessages");
}
}
</p>

If the ResourceBundleMessageInterpolator cacheMessages is static variable then it may solve our problem. By default it is setting to true.

And here is test scenario

1. Statring the websphere application server.
2. Login to the application and invoking the product search page (for example)
3. Clicking the submit button without entering the search fields will prompts error message say "please select mandatory fields to search" from ValidationMessages.properties
4. Changed the ValidationMessages.properties message to "please select necessary fields to search"
5. Invoke the CustomeMessageInterpolator.jsp to reload updated resource bundle (This page will updated properties from the DB and to write ValidationMessages.properties. Above code included in this logic after writing properties file)
6. Click submit button on product search page without entering the search fileds is prompts same error message.

Please give me some tips to resolve this.

Thank you


Top
 Profile  
 
 Post subject: Re: How to refresh ResourceBundle dynamically without stoping???
PostPosted: Mon Jun 21, 2010 5:23 am 
Hibernate Team
Hibernate Team

Joined: Thu Apr 05, 2007 5:52 am
Posts: 1689
Location: Sweden
Quote:
Its reloading the Resource bundle, when ResourceBundleMessageInterpolator cacheMessages=false. I have tested this by changing cacheMessages=false in debug mode.

So it actually works. What I don't understand is why you have to set the flag to false using the debugger. If your bootstrapping is setup properly the flag should be true.


Quote:
HibernateValidatorConfiguration configuration = Validation.byProvider(HibernateValidator.class).configure();
ResourceBundleLocator defaultResourceBundleLocator = configure.getDefaultResourceBundleLocator();
ResourceBundleLocator myResourceBundleLocator = new MyCustomResourceBundleLocator(defaultResourceBundleLocator);
configuration.messageInterpolator(new ResourceBundleMessageInterpolator(myResourceBundleLocator, false));

//MyCustomResourceBundleLocator
public class MyCustomResourceBundleLocator implements ResourceBundleLocator
{

private PlatformResourceBundleLocator delegate;

MyCustomResourceBundleLocator(ResourceBundleLocator locator)
{
this.delegate = (PlatformResourceBundleLocator) locator;
}

@Override
public ResourceBundle getResourceBundle(Locale locale) {
return ResourceBundle.getBundle("ValidationMessages");
}
}

Looks ok, but I am missing the last bits where you create the ValidatorFactory and Validator. Where and how is that done?

Quote:
If the ResourceBundleMessageInterpolator cacheMessages is static variable then it may solve our problem. By default it is setting to true.

That's a no go. This would mean that all ResourceBundleMessageInterpolator in the JVM share the same value. The whole point is that you are able to
bootstrap multiple ValidatorFactory instances with different behavior.

Where is your Validator coming from in your usecase? Which ValidatorFactory creates it and how? Do you call the Validator yourself or do you use for example validation via JPA event listeners (or something similar)?

--Hardy


Top
 Profile  
 
 Post subject: Re: How to refresh ResourceBundle dynamically without stoping???
PostPosted: Tue Jun 22, 2010 3:29 am 
Newbie

Joined: Tue Jun 01, 2010 2:20 am
Posts: 10
Hi Hardy,

Here is my test case which works fine

@Test
public void testProductSearch() throws Exception
{
ProductSearch search = new ProductSearch();
search.setProductID(null);
search.setProductName(null);

ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
validator = factory.getValidator();
Set<ConstraintViolation<ProductSearch>> constraintViolations = validator.validate(search);
System.out.println(constraintViolations);

//Change ValidationMessages.properties error message in debug mode and proceed
Configuration<?> configuration = Validation.byDefaultProvider().configure();
ResourceBundleLocator myResourceBundleLocator = new MessagesResourceBundleLocator();
factory = configuration.messageInterpolator(new ResourceBundleMessageInterpolator(myResourceBundleLocator, false)).buildValidatorFactory();
validator = factory.getValidator();

constraintViolations = validator.validate(search);
System.out.println(constraintViolations);

}

It doesn't work in web application, the test scenario as described in my previous quote.

Here is my web application code

ProductSearch.java
-------------------

@ValidProductSearchFields
public class ProductSearch{
..............
}


ValidProductSearchFields.java
-----------------------------
@Target( { TYPE, METHOD, FIELD, ANNOTATION_TYPE })
@Retention(RUNTIME)
@Constraint(validatedBy = ValidProductSearchFieldsValidator.class)
@Documented
public @interface ValidProductSearchFields {
String message() default "{pr.search.messages}";

Class<?>[] groups() default {};

Class<? extends Payload>[] payload() default {};
}


ValidProductSearchFieldsValidator.java
-------------------------------------
public class ValidProductSearchFieldsValidator implements
ConstraintValidator< ValidProductSearchFields, ProductSearch> {

public void initialize( ValidProductSearchFields constraintAnnotation) {

}

public boolean isValid(ProductSearch search, ConstraintValidatorContext constraintContext) {
if((Util.isNullOrEmptyOrBlank(search.getProductID())&& Util.isNullOrEmptyOrBlank(search.getProductName())){
return false;
}else{
return true;
}
}


private Set<ConstraintViolation<ProductSearch>> validate(String userID, String abn,String entityName){
ProductSearch search = new ProductSearch();
search.setProductID(userID);
search.setProductName(abn);
return Validation.buildDefaultValidatorFactory().getValidator().validate(search);
}
}


Could you please let me know do I have to use the following statements for each request?
configuration.messageInterpolator(new ResourceBundleMessageInterpolator(myResourceBundleLocator, false));

Thank you


Top
 Profile  
 
 Post subject: Re: How to refresh ResourceBundle dynamically without stoping???
PostPosted: Tue Jun 22, 2010 4:09 am 
Hibernate Team
Hibernate Team

Joined: Thu Apr 05, 2007 5:52 am
Posts: 1689
Location: Sweden
Hi,

Code:
return Validation.buildDefaultValidatorFactory().getValidator().validate(search);


It seems you are building a default validator factory for each call of validate(String userID, String abn,String entityName). First of all this will of course not use your custom resource bundle locator. You will have to do the same as in your unit tests. Secondly, you should not bootstrap the Validation framework for each single validation call. The idea is to create a ValidatorFactory and keep it around. For each validation call you then just call factory.getValidator();

--Hardy


Top
 Profile  
 
 Post subject: Re: How to refresh ResourceBundle dynamically without stoping???
PostPosted: Wed Jun 23, 2010 1:39 am 
Newbie

Joined: Tue Jun 01, 2010 2:20 am
Posts: 10
Hi Hardy
Quote:
It seems you are building a default validator factory for each call of validate(String userID, String abn,String entityName)


I have created new class to get validatorFactory.
Here is my test code

Code:

public class SchValidator
{
   private static ValidatorFactory factory;
   
   public ValidatorFactory getValidatorFactory(boolean isCustom)
   {
               // pass isCustom=false to test ResourceBundle reloading.
               // test by changing the messages at ValidatorMessage.properties
      if (factory == null || !isCustom)
      {
HibernateValidatorConfiguration configure = Validation.byProvider(HibernateValidator.class).configure();
ResourceBundleLocator defaultResourceBundleLocator = configure.getDefaultResourceBundleLocator();
ResourceBundleLocator myResourceBundleLocator = new MyCustomResourceBundleLocator(defaultResourceBundleLocator);
configure.messageInterpolator(new ResourceBundleMessageInterpolator(myResourceBundleLocator, false));
factory = configure.messageInterpolator(new ResourceBundleMessageInterpolator(
      myResourceBundleLocator, isCustom)).buildValidatorFactory();
       }
      return factory;
   }
}



I am calling the above method from my ValidProductSearchFieldsValidator.java

Code:
public boolean isValid(ProductSearch search, ConstraintValidatorContext constraintContext)
{
        getValidatorFactory(true).getValidator();
   if((Util.isNullOrEmptyOrBlank(search.getProductID())&& Util.isNullOrEmptyOrBlank(search.getProductName()))
   {
      return false;
   }
   else
   {
      return true;
   }
}


The messageInterpolator cacheMessage=false when I inspect validatorFactory variables for getValidatorFactory(true).getValidator();.

But always cacheMessage=true at ResourceBundleMessageInterpolator.interpolateMessage. Some how ValidatorContext is setting messageInterpolator.

This code doesn't help me. I am not getting where am I missing?
Could you please give me some code sample?

Thank you


Top
 Profile  
 
 Post subject: Re: How to refresh ResourceBundle dynamically without stoping???
PostPosted: Wed Jun 23, 2010 4:19 am 
Hibernate Team
Hibernate Team

Joined: Thu Apr 05, 2007 5:52 am
Posts: 1689
Location: Sweden
msreddy wrote:
Hi Hardy
Quote:
I am calling the above method from my ValidProductSearchFieldsValidator.java

Code:
public boolean isValid(ProductSearch search, ConstraintValidatorContext constraintContext)
{
        getValidatorFactory(true).getValidator();
   if((Util.isNullOrEmptyOrBlank(search.getProductID())&& Util.isNullOrEmptyOrBlank(search.getProductName()))
   {
      return false;
   }
   else
   {
      return true;
   }
}




This does not make any sense at all and will certainly not change anything. When you call getValidatorFactory(true).getValidator(); within a ConstraintValidator you are already in the middle of a validation. You have to use the Validator returned by getValidatorFactory(true).getValidator(); to do the actual validation! I recommend you go read through the online manual and Bean Validation specification to understand the difference between the bootstrapping and validation phases.

--Hardy


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 18 posts ]  Go to page 1, 2  Next

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.