Use Spring ressource bundle with Hibernate Validator - java

First time posting here.
I'm developing a JSON webservice API and I'm tring to use custom validation message with no success.
Here is my setup (focus on component involved in my problem. I also use MyBatis, jUnit...) :
Tomcat 8.0.14
Spring 4.1.1
Jersey 2.13
Jersey-spring3 2.13
Jersey-bean-validation
Hibernate Validator 5.0.0.Final
Bean property validation and class-level validation work fine.
Now I'm trying to setup custom error validation messages.
I don't wan't to use the JSR-303 /META-INF/ValidationMessages.properties but I wan't to use a spring managed bundle.
In my applicationContext.xml, I defined :
<bean name="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean">
<property name="validationMessageSource">
<ref bean="messageSource" />
</property>
</bean>
<bean name="messageSource"
class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<property name="basename" value="configuration/messages/validation" />
</bean>
I also create a /WEB-INF/classes/configuration/messages/validation_fr_FR.properties with some properties :
model.error=Modèle invalide
Now when I try to validate my Bean I get this in my logs :
15:47:14,300 DEBUG http-nio-8080-exec-2 resourceloading.PlatformResourceBundleLocator:72 - ValidationMessages not found.
15:47:45,707 DEBUG http-nio-8080-exec-2 resourceloading.PlatformResourceBundleLocator:69 - org.hibernate.validator.ValidationMessages found.
No mention to my bundle here...
In my JSON response, I get :
{model.error} (path = EventServiceAPIImpl.createOrUpdateEvent.arg0, invalidValue = fr.bz.pdcv.bean.Event#d99af88)
{model.error} is not replaced with my custom message.
I think my ReloadableResourceBundleMessageSource is overridden by Hibernate Validator default configuration. But why ?
I overload google and stackoverflow to find a solution, I didn't find anythings which can help me
Does someone encounter the same issue ?
Thank you !

Though I guess i am late but it may help someone else.
Rename your validation_fr_FR.properties with ValidationMessages.properties file and put that inside the folder 'src\main\resources'.
So your final path will be as follows:
src\main\resources\ValidationMessages.properties
Restart the server and try to render the validation.
U no more need the LocalValidatorFactoryBean and ResourceBundleMessageSource
Hibernate basically looks for the same file name in the default directory and overwrites the default ValidationMessages.properties

Related

How to consume an EJB in Spring?

I'm trying to inject the EJB with a Spring application in a Websphere server to call his methods.
I downloaded the EJB's jar and added it as a Library in the project.
The jar exposes a Remote, which is an interface.
1: EJB Jar in Libraries
Then I tried to make Spring understand that it is an EJB.
I put this inside web.xml
<description />
<ejb-ref-name>ejb/AberturaEJBRemoteRef</ejb-ref-name>
<ejb-ref-type>Session</ejb-ref-type>
<home />
<remote>
br.com.zzz.xxx.servcaptura.abertura.ejb.AberturaEJBRemote
</remote>
<ejb-link>AberturaEJB</ejb-link>
</ejb-ref>
Then I tried these two configurations at app.context:
First attempt:
<jee:remote-slsb id="abertura" jndi- name="ejb/AberturaEJBRemoteRef#br.com.zzz.xxx.servcaptura.abertura.ejb.AberturaEJBRemote"
business-interface="br.com.zzz.xxx.servcaptura.abertura.ejb.AberturaEJBRemote"
home-interface="br.com.zzz.xxx.servcaptura.abertura.ejb.AberturaEJBRemote"
cache-home="false" lookup-home-on-startup="false"
refresh-home-on-connect-failure="true" />
Second attempt:
<bean id="abertura"
class="org.springframework.ejb.access.LocalStatelessSessionProxyFactoryBean" lazy-init="true">
<property name="jndiName" value="ejb/AberturaEJBRemoteRef" />
<property name="businessInterface" value="br.com.zzz.xxx.servcaptura.abertura.ejb.AberturaEJBRemote" />
</bean>
<bean id="acompanhamentoWebService" class="br.com.zzz.xxx.integracaosinistro.servacompws.webservice.AcompanhamentoWebService">
<property name="abertura">
<ref bean="abertura" />
</property>
</bean>
Inside a class, I'm doing this:
#Service
#WebService
public class AcompanhamentoWebService {
#Autowired(required = true)
private AberturaEJBRemote abertura;
...
The second one Spring can't understand that it is a bean.
On the first configuration attempt, with jee:remote-slsb, here I'm getting error after call the EJB method:
name: ejb/AberturaEJBRemoteRef#br.com.zzz.xxx.servcaptura.abertura.ejb.AberturaEJBRemote: First component in name AberturaEJBRemoteRef#br.com.zzz.xxx.servcaptura.abertura.ejb.AberturaEJBRemote not found. [Root exception is org.omg.CosNaming.NamingContextPackage.NotFound: IDL:omg.org/CosNaming/NamingContext/NotFound:1.0]
I really don't know if I am trying this correctly, cause I never work with EJB before.
Call the remote inside the jar is a correct approach?
What do you think I'm doing wrong?
Sorry for the bad English.
Thanks.
UPDATE
I founded an example and it seems that my approach is ok. But it missing an EJB configuration inside Websphere. To call the EJB remotely, I read that I will need the server informations where the EJB is stored and available.
And I don't have this information yet.
I think that I could access the methods from EJB directly from the jar. But I understood that it's not like this.
I will come back here when the problem was solved or another information appears.

Marklogic XCC ContentSource using JNDI

I'm trying to get a Marklogic ContentSource object loaded from Tomcat's context.xml using JNDI and Spring.
I'm using Tomcat 8.5, and Spring 2.5 (unfortunately)
I have added the following to context.xml in Tomcat
<Resource name="MLContentSource" auth="Container" type="com.marklogic.xcc.ContentSource"
factory="com.marklogic.xcc.jndi.ContentSourceBeanFactory"
url="xcc://username:password#mymarklogic-server/DatabaseName"/>
And the following in my applicationContext.xml
<bean id="contentSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="java:comp/env/MLContentSource"/>
</bean>
I have another bean declared in my applicationContext.xml that relies on the ContentSource bean. Its expecting a property to be set that is of type com.marklogic.xcc.ContentSource
<bean id="marklogicRepository" class="org.example.repository.ingestion.MarkLogicRepositoryImpl">
<property name="contentSource" ref="contentSource" />
</bean>
The issue is that the contentSource bean is of type JndiObjectFactoryBean and not com.marklogic.xcc.ContentSource. Is there something I'm missing to get a proper ContentSource from the JndiObjectFactoryBean?
It turns out the above code actually worked, my IDE was complaining about types but Spring will automatically cast the object stored inside JndiObjectFactoryBean to the target type at runtime.
Maybe try XQJ?
https://github.com/cfoster/xqj-pool-example/blob/master/src/main/java/simple/WithJNDI.java
http://xqj.net/
The XQuery API for Java
A standard Java interface to XML DataSources which support XQuery 1.0.
The XQJ API is to XML Databases as the JDBC API is to Relational Databases.
Is a light-weight design and is very easy to pick up.

Using custom registries within apache camel

Apache Camel does not seem to support any bean that is to be used within its registry. I am currently trying to add an AWS S3 Client object/bean to the spring configuration without any luck. The bean itself is added to the registry, but when camel goes to use the client object it throws an error similar to this:
Caused by: java.lang.IllegalArgumentException: Could not find a
suitable setter for property: amazonS3Client as there isn't a setter method
with same type: java.lang.String nor type conversion possible: No type
converter available to convert from type: java.lang.String to the
required type: com.amazonaws.services.s3.AmazonS3 with value
#amazonClient
The amazonClient is the aforementioned bean that is added appropriately the spring config which has led me to believe the camel config is indeed finding the bean. Here is the related xml configuration:
<!-- set up default amazon s3 client from amazon aws sdk -->
<bean id="amazonClient" class="com.amazonaws.services.s3.AmazonS3Client">
<constructor-arg>
<bean class="com.amazonaws.auth.BasicAWSCredentials">
<constructor-arg name="accessKey" value=""/>
<constructor-arg name="secretKey" value=""/>
</bean>
</constructor-arg>
</bean>
Within the camel context section (you can see the bean is mentioned):
<camel:route id="importFilesFromS3">
<camel:from uri="aws-s3://intuit-commerce-imports?amazonS3Client=#amazonClient&region=us-west-2&deleteAfterRead=true"/>
<camel:to uri="ref:importProcessingEndpoint"/>
</camel:route>
Apache camel claims to have this feature in their documentation, but I have found a few sources that come across the same issue. The answer in the link does not provide much explanation.
I've never worked with AWS S3, but I also ran into a similar problem with Camel seemingly not able to find the bean within the Spring registry.
By stepping through IntrospectionSupport.setProperty, I noticed that CamelContextHelper.lookup was using JndiRegistry instead of the ApplicationContextRegistry.
My solution was to add camel-spring as a project dependency, as well as to initialize my camel context with ApplicationContextRegistry:
camelContext = new DefaultCamelContext(new ApplicationContextRegistry(applicationContext));

Referencing a value from a spring config

First a bit of setup info:
I have a multi-tenant spring based application. The multi-tenant enabling library is an in-house developed tool where I work that I have to use. How it works is that there is an interceptor that sets in front of the servlet for the application. Upon a request hitting the servlet it loads a tenant specific spring config for "stuff" needed for the tenant specified on the url hitting the servlet.
As stated, the above is just a bit of background. Now to the issue/question:
What I want to do is to create, in the tenant configuration that is loaded, a value that I can use to inject where I need. So, is there a way I can just define a constant in a spring config and then reference it via #Value or #Resource in java code?
There will be no bean implementation behind it, it would just be purely and only a key/value that I can reference where needed in my application by name. So, something to the effect of:
<bean name="MyIdentifier">
<property name="theId" value="1001" />
</bean>
And then can I do something like?
#Value{MyIdentifier.theId}
String theId;
And have Spring be aware of and inject the value. The problem is that doing something like above Spring complains there is no implementation for the bean. Notice, no class specified for the bean. The reason I want to do this is every tenant config file will contain this bean, but the actual value will vary per tenant.
Is there some other type to use in the config to do this? If so, what schemas have to be on the config?
I am guessing I am either trying to make Spring do something not intended, or, this is so simple I cannot see it since I have stared at it too long. Anyway, thanks for the help.
You can not create bean tag in configuration file without providing class implementation. If you want to inject the value of fields, you have to go for properties file instead.
Create property file as below:
application.properties
theId=1001
Load property file in your configuration:
<bean class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer">
<property name="ignoreUnresolvablePlaceholders" value="true"/>
<property name="locations">
<list>
<value>classpath:application.properties</value>
</list>
</property>
</bean>
And access the property in your concrete class:
#Value("${theId}")
String theId;

working with JTATransactionManager in spring?

I am trying to use JtaTransactionManager in spring/hibernate. I have below configuration.
<bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager">
<property name="userTransactionName" value="java:comp/UserTransaction"></property>
</bean>
Now can i mark my service methods with #Transactional ? or do i need any extra configuration to use #Transactional ? do i need to add ?
An annotation is nothing more then metadata, so only slapping an annotation on there and expect it to magically work isn't going to happen.
To make #Transactional work you need to tell spring that you want to use annotation to drive your transactions. For this add the <tx:annotation-driven /> tag to your configuration.
However that probably isn't going to be all there is needed as you also need to configure hibernate appropriately for JTA.
A small tip instead of defining the bean, use the shorter <tx:jta-transaction-manager />. This will do some detection on which app server you are running and configure the appropriate transaction manager for you. See http://docs.spring.io/spring/docs/current/spring-framework-reference/html/transaction.html#transaction-application-server-integration for more information.

Categories