I have written an application that calls a service through Spring's RestTemplate.
It's working fine when I call the URL http://localhost:8081/index/myservice directly.
I tried configuring an endpoint using application.properties, how do I link it to the method calling the URL ? As it is now, It doesn't have any effect.
application.properties
app.endpoint = http://localhost:8081/index/
I want to directly call app.endpoint instead of writing the URL.
Update : ApplicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<!-- Rest Template -->
<bean id="restTemplate" class="org.springframework.web.client.RestTemplate">
</bean>
<bean id="properties" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="locations">
<list><value>classpath:application.properties</value></list>
</property>
So to call the URL from the method : You can use the #Value annotation like this :
#Value("${app.endpoint}")
private String appEndpoint;
The configuration in your XML :
<context:property-placeholder location="classpath:placeholder.properties"/>
HTH,
Gyan
Related
We were using 4.2.x version of spring and we are using BeanFactoryLocator to create a factory from xml file.
method to return Beanfactory:
private BeanFactory createServicesContainer() {
BeanFactoryLocator bfLocator = SingletonBeanFactoryLocator.getInstance("Connector.xml");
BeanFactoryReference bfReference = bfLocator.useBeanFactory("bigBean");
return bfReference.getFactory();
}
my Connector.xml file contains:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"
default-lazy-init="false">
<!--
The Big Bean for accessing all the repository services. This factory bean serves as
and umbrella bean for all the underlying repository services.
-->
<bean id="bigBean" class="org.springframework.context.support.ClassPathXmlApplicationContext">
<constructor-arg>
<list>
<value>sample1-connector.xml</value>
<value>sample2-connector.xml</value>
<value>sample3-connector.xml</value>
</list>
</constructor-arg>
</bean>
</beans>
Now how can make changes it to work in Spring 5.x
I have an active profile problem.
Decided to look in debug mode on my context
(profile indepenent contexts works in such way to in my case -
getBeanDefinitionNames returns empty array).
new FileSystemXmlApplicationContext with mentioned file works without exceptions in code fragment mode.
Code
new FileSystemXmlApplicationContext(
"D:\\Projects\\opti\dao\\src\\main\\resources\\contexts\\" +
"\\profiles\\test.xml")
This context with
getBeanDefinitionNames()
returns empty array.
D:\Projects\opti\dao\src\main\resources\contexts\profiles\test.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<beans profile="test">
<context:property-placeholder properties-ref="properties" ignore-resource-not-found="false"/>
<bean id="properties" lazy-init="false"
class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="locations">
<list>
<value>classpath*:properties/test-database.properties</value>
</list>
</property>
</bean>
</beans>
</beans>
Spring 4.2.5
D:\Projects\opti\dao\src\main\resources\properties\test-database.properties
connection.driverClassName=org.hsqldb.jdbc.JDBCDriver
connection.url=jdbc:hsqldb:mem:test
connection.userName=sa
connection.password=
For use beans of a specific profile you should start the jvm with -Dspring.profiles.active=test, or setting spring.profiles.active=test as env variable System.setProperties(props) could be a way for configure it.
I hope that this can help you
I'm having a problem with RESTlet Framework configuration with Spring. I want to have one global filter for all requests and responses. I guess I can use Filter class and it's methods beforeHandle, afterHandle and setNext like this:
Filter.beforeHandle() -> Router -> Filter.afterHandle()
The problem is, that I'm using Spring configured RESTlet and I don't know if the regular Filter will work correctly with SpringRouter from org.restlet.ext.spring package. My current restlet configuration is as follows:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="root" class="org.restlet.ext.spring.SpringRouter">
<property name="attachments">
<map>
<entry key="/login">
<bean class="org.restlet.ext.spring.SpringFinder">
<lookup-method name="create"
bean="loginResource" />
</bean>
</entry>
</map>
</property>
</bean>
</beans>
I'm thinking about adding a bean with id root and class that extends class Filter, and pass to it as property next a bean with id router (which currently is called root). What do you think about this solution?
Mixing Restlet classes from the Spring extension with other one shouldn't be an issue. Spring* classes only provide additional configurability.
I have a Spring 3.1 application, and I try to use a system variable in the context files. The variable "JAVA_MY_ENV" is defined on my System (on Windows, it is in the "System variables", from the control panel).
In web.xml, I can use it as a variable and it works, it is successfully replaced by the actual value of the variable (let's say "electrotype") :
<listener>
<listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
</listener>
<context-param>
<param-name>log4jConfigLocation</param-name>
<param-value>classpath:log/${JAVA_MY_ENV}.log4j.properties</param-value>
</context-param>
I can also use it in my main "bean" context, to do an import, and it also works :
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.1.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.1.xsd">
<!-- (...) -->
<import resource="classpath:spring/app-config.xml" />
<import resource="classpath:spring/env/context-env-${JAVA_MY_ENV}.xml" />
</beans>
But In "app-config.xml", one of my other context file, I try this and it doesn't work :
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.1.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.1.xsd">
<bean id="appConfiguration" class="com.xxx.app.AppConfiguration">
<constructor-arg value="${JAVA_MY_ENV}" />
</bean>
</beans>
The com.xxx.app.AppConfiguration receives the String "${JAVA_MY_ENV}" as the constructor parameter, not the interpreted value of it!
I'm not sure to understand where the ${} variables are interpreted and where they are not.
Is there a way I can pass the interpreted ${JAVA_MY_ENV} value to my com.xxx.app.AppConfiguration constructor?
As of 3.0 in Spring you should be to inject values into properties
#Value("#{ systemProperties['JAVA_MY_ENV'] }")
private String myVar;
or
<property name ="myVar" value="#{systemProperties['JAVA_MY_ENV']}"/>
Alternatively you can look into using the PropertySourcesPlaceholderConfigurer or similar class. Creating this will tell spring how to look for variables. Often i make a number of property files as well so that environment and internal property file values are available to the app. e.g.
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:someprops.properties</value>
</list>
</property>
<property name="ignoreResourceNotFound" value="true" />
<property name="searchSystemEnvironment" value="true" />
<property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE" />
A key element in the above example is the "searchSystemEnvironment" being set to true. This tells spring to use env variables (which is what you want)
Possible duplicate of <context:property-placeholder> properties not accessible to the child (web) context
As I understand this is expected behavior. You should inject beans only in servlet context or to include configuration bean into servlet-context.xml
To use a PropertyPlaceholderConfigurer, suggested by BruceLowe, works. Another way (maybe more complicated) I found to resolve a specific property is using :
<bean id="JAVA_MY_ENV" class="org.springframework.util.SystemPropertyUtils" factory-method="resolvePlaceholders">
<constructor-arg value="${JAVA_MY_ENV}" />
</bean>
This creates a String bean containing the resolved value of ${JAVA_MY_ENV}!
Then I can use this bean anywhere a bean ref can be used. For example as a constructor-arg:
<bean id="appConfiguration" class="com.xxx.app.AppConfiguration">
<constructor-arg ref="JAVA_MY_ENV" />
</bean>
So now I use ${JAVA_MY_ENV} in places where it is interpreted, without adding PropertyPlaceholderConfigurer, and the JAVA_MY_ENV bean otherwise.
Does somebody know how to integrate the cxf framework without using the cxf plugin? I have already published a simple service, but my problem is to inject existing grails service bean in the cxf jaxws bean.
In applicationContext.xml i'm using following definition
<jaxws:server id="jaxwsService" serviceClass="at.pdts.cxf.HelloWorld" address="/hello">
<jaxws:serviceBean>
<bean class="at.pdts.cxf.HelloWorldImpl">
<property name="halloService"><ref bean="helloWorld"></ref></property>
</bean>
</jaxws:serviceBean>
</jaxws:server>
The helloWorld bean is a normal grails serivce class. During startup i get following exception.
Cannot resolve reference to bean 'helloWorld' while setting bean
property 'halloService'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'helloWorld' is defined
applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jaxws="http://cxf.apache.org/jaxws"
xsi:schemaLocation="
http://cxf.apache.org/jaxws
http://cxf.apache.org/schemas/jaxws.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<import resource="classpath:META-INF/cxf/cxf.xml"/>
<import resource="classpath:META-INF/cxf/cxf-servlet.xml" />
<import resource="classpath:META-INF/cxf/cxf-extension-soap.xml"/>
<bean id="grailsApplication" class="org.codehaus.groovy.grails.commons.GrailsApplicationFactoryBean">
<description>Grails application factory bean</description>
<property name="grailsDescriptor" value="/WEB-INF/grails.xml" />
<property name="grailsResourceLoader" ref="grailsResourceLoader" />
</bean>
<bean id="pluginManager" class="org.codehaus.groovy.grails.plugins.GrailsPluginManagerFactoryBean">
<description>A bean that manages Grails plugins</description>
<property name="grailsDescriptor" value="/WEB-INF/grails.xml" />
<property name="application" ref="grailsApplication" />
</bean>
<bean id="grailsConfigurator" class="org.codehaus.groovy.grails.commons.spring.GrailsRuntimeConfigurator">
<constructor-arg>
<ref bean="grailsApplication" />
</constructor-arg>
<property name="pluginManager" ref="pluginManager" />
</bean>
<bean id="grailsResourceLoader" class="org.codehaus.groovy.grails.commons.GrailsResourceLoaderFactoryBean">
<property name="grailsResourceHolder" ref="grailsResourceHolder" />
</bean>
<bean id="grailsResourceHolder" scope="prototype" class="org.codehaus.groovy.grails.commons.spring.GrailsResourceHolder">
<property name="resources">
<value>classpath*:**/grails-app/**/*.groovy</value>
</property>
</bean>
<bean id="characterEncodingFilter"
class="org.springframework.web.filter.CharacterEncodingFilter">
<property name="encoding">
<value>utf-8</value>
</property>
</bean>
<jaxws:server id="jaxwsService" serviceClass="at.pdts.cxf.HelloWorld" address="/hello">
<jaxws:serviceBean>
<bean class="at.pdts.cxf.HelloWorldImpl">
<property name="halloService"><ref bean="halloService"></ref></property>
</bean>
</jaxws:serviceBean>
</jaxws:server>
</beans>
HelloWorldImpl.groovy
package at.pdts.cxf
import javax.jws.WebService
#WebService(endpointInterface = "at.pdts.cxf.HelloWorld")
public class HelloWorldImpl implements HelloWorld {
def halloService // inject HelloService. Initialize this bean via applicationContext.xml
public String sayHi(String text) {
return "hello " + halloService.scream(text)
}
}
HelloService.groovy
class HalloService implements InitializingBean{
static transactional = false
String scream(String text) {
text.toUpperCase()
}
// methods gets not called, so service bean is not initialized at the ws creation time
void afterPropertiesSet() {
println "------> initializing bean HalloSerivce <--------
}
}
It seems that at the moment of the jaxwsService initialization the helloWorld service bean is not available.
This needs to point to something:
<ref bean="helloWorld">
Do you have something like this defined:
<bean id="helloWorld" class="at.pdts.cxf.HalloServiceImpl" />
That error means that Spring could now find a spring bean with the alias "helloWorld."
Perhaps posting your entire spring.xml and the java code to HelloWorldImpl would help.
EDIT: Your config confirms my theory.
<ref bean= says "inject something else here". But you have not defined that bean, hence the exception No Such Bean Definition. Furthermore, I was able to make your code work by creating my own implementation of HalloService (HalloServiceImpl) with a custom scream method that returned a blank string. Then I added it to the spring configuration: <bean id="helloWorld" class="at.pdts.cxf.HalloServiceImpl" />
EDIT #2: Another way to make it work is by eliminating HalloService:
<jaxws:server id="jaxwsService" serviceClass="at.pdts.cxf.HelloWorld" address="/hello">
<jaxws:serviceBean>
<bean class="at.pdts.cxf.HelloWorldImpl" />
</jaxws:serviceBean>
</jaxws:server>
</beans>
HelloWorldImpl.groovy
package at.pdts.cxf
import javax.jws.WebService
#WebService(endpointInterface = "at.pdts.cxf.HelloWorld")
public class HelloWorldImpl implements HelloWorld {
public String sayHi(String text) {
return "hello scream!" + text
}
}
Basically your choices are: Provide Spring an implmentation of HalloService, or don't reference it in your Spring.xml.
EDIT #3: There is a misunderstanding around the purpose of InitializingBean:
From the javadoc:
InitializingBean Interface to be implemented by beans that need to
react once all their properties have been set by a BeanFactory: for
example, to perform custom initialization, or merely to check that all
mandatory properties have been set.
Implementing InitializingBean just means that afterPropertiesSet() will be called. It does not mean the Spring will automatically add this bean to your Spring Config. You still must declare the bean in your spring configuration with this line:
<bean id="halloService" class="at.pdts.cxf.HalloService" />
I missed this the first time I read your question but you are defining your bean in applicationContext.xml. When I was making a test case for your question, I was putting my bean definition in grails-app/conf/spring/resources.xml. Try creating that file and putting the following into it:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:lang="http://www.springframework.org/schema/lang"
xmlns:jaxws="http://cxf.apache.org/jaxws"
xsi:schemaLocation="
http://cxf.apache.org/jaxws
http://cxf.apache.org/schemas/jaxws.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<import resource="classpath:META-INF/cxf/cxf.xml" />
<import resource="classpath:META-INF/cxf/cxf-extension-soap.xml" />
<import resource="classpath:META-INF/cxf/cxf-servlet.xml" />
<!--create the bean for the service, link to groovy service bean -->
<jaxws:server id="jaxwsService" serviceClass="at.pdts.cxf.HelloWorld" address="/hello">
<jaxws:serviceBean>
<bean class="at.pdts.cxf.HelloWorldImpl">
<property name="halloService" ref="halloService" />
</bean>
</jaxws:serviceBean>
</jaxws:server>
</beans>
As a side note, you can find more information about integrating Grails and CXF here.