SpringMethodInvocationBean: Argument is an Interface - spring

<bean id="arrayDescriptor"
class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="targetObject">
<value>oracle.sql.ArrayDescriptor</value>
</property>
<property name="targetMethod">
<value>createDescriptor</value>
</property>
<property name="arguments">
<list>
<value>UDB_NAME</value>
<value>#{database.getConnection()}</value>
</list>
</property>
</bean>
I can't seem to make the method work because it needs an argument of (String, java.sql.Connection) instead its getting (String, org.basic.datasource.PoolableConnection).
Is it possible to typecast on EL? I have research its not possible.
Can I use another spring api to run a method and an argument?
Is it possible to instantiate in Spring at interface? I have research and it is not possible.

First of all the ArrayDescriptor.createDescriptor() requires DataSource, not a connection. I guess database represents DataSource, try:
<value>#{database}</value>
or even:
<ref bean="database"/>
What about using Java configuration and avoiding this XML hell?
#Configuration
public class Cfg {
#Resource
private DataSource database;
#Bean
public ArrayDescriptor arrayDescriptor() {
return ArrayDescriptor.createDescriptor("UDB_NAME", database);
}
}

Related

consul properties in xml configuration

I am trying to use consul for centralised configuration for spring application. When I use annotation based configuration like Example 1 it works perfectly.
//Example 1
#Configuration
#EnableConsulPropertySource({"root/api/defaults", "root/global/defaults"})
public class ApplicationConfiguration {
#Value("httpclient.pool.maxtotal")
private int maxTotal;
#Value("httpclient.pool.defaultmaxperroute")
private int maxPerRoute;
...
}
However I could not find a way to use consul properties directly in xml.
<bean id="properties" class="org.springframework.SomeBeanToEnableConsulInXMLConfig">
<property name="locations">
<list>
<value>root/api/defaults</value>
<value>root/global/defaults</value>
</list>
</property>
</bean>
...
<bean name="http.client" class="com.xxx.HTTPClient">
<property name="maxTotal" value="${httpclient.pool.maxtotal}" />
<property name="defaultMaxPerRoute" value="${httpclient.pool.defaultmaxperroute}" />
</bean>
Does spring has something like SomeBeanToEnableConsulInXMLConfig or any hints on implementing this class?

Java based approach for injecting list of spring beans

I am trying to get rid of my XML beans definition file. I would like to know how can i convert the following XML configuration to Java code.
<bean id="CustomerBean" class="com.java2s.common.Customer">
<property name="lists">
<bean class="org.springframework.beans.factory.config.ListFactoryBean">
<property name="targetListClass">
<value>java.util.ArrayList</value>
</property>
<property name="sourceList">
<list>
<value>1</value>
<value>2</value>
<value>3</value>
</list>
</property>
</bean>
</property>
</bean>
I am especially interested in knowing how to convert a list, Set, Map and properties XML configurations to Java code.
And if in a list if i have defined the beans in order like
<bean p:order="1000"
How i can manage the same ordering in java code.
A <list> corresponds to java.util.List, <map> corresponds to java.util.Map, <props> corresponds to java.util.Properties and so on.
To set the order, use the org.springframework.core.annotation.Order annotation on your bean or let it implement org.springframework.core.Ordered.
The equivalent of your XML configuration is something like:
#Bean
public Customer CustomerBean() {
Customer customer = new Customer();
List<String> lists = new ArraysList<>();
lists.add("1");
lists.add("2");
lists.add("3");
customer.setLists(lists);
return customer;
}
Note that the name of the method will be the name of the bean.

Spring MVC REST produces XML on default

I have a problem with Spring MVC and REST. The problem is that when i post a url without extension or whatever extension other then json or html or htm i am always getting an xml response. But i want it to default to text/html response. I was searching in many topics and cant find the answear to this.
Here is my Controller class :
#RequestMapping(value="/user/{username}", method=RequestMethod.GET)
public String showUserDetails(#PathVariable String username, Model model){
model.addAttribute(userManager.getUser(username));
return "userDetails";
}
#RequestMapping(value = "/user/{username}", method = RequestMethod.GET,
produces={"application/xml", "application/json"})
#ResponseStatus(HttpStatus.OK)
public #ResponseBody
User getUser(#PathVariable String username) {
return userManager.getUser(username);
}
Here is my mvc context config:
<mvc:resources mapping="/resources/**"
location="/resources/"/>
<context:component-scan
base-package="com.chodak.controller" />
<bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
<property name="defaultContentType" value="text/html" />
<property name="mediaTypes">
<map>
<entry key="json" value="application/json"/>
<entry key="xml" value="application/xml"/>
</map>
</property>
</bean>
<bean id="viewResolver"
class="org.springframework.web.servlet.view.UrlBasedViewResolver">
<property name="viewClass">
<value>
org.springframework.web.servlet.view.tiles3.TilesView
</value>
</property>
</bean>
<bean id="tilesConfigurer"
class="org.springframework.web.servlet.view.tiles3.TilesConfigurer">
<property name="definitions">
<list>
<value>/WEB-INF/tiles.xml</value>
</list>
</property>
</bean>
Actually when I tried the built in Eclipse browser it works fine, but when I use firefox or chrome it shows xml response on a request with no extension. I tried using ignoreAcceptHeader, but no change.
Also works on IE :/
If anyone has an idea please help, Thank you.
I actually found out how to do it, i dont really understand why but it is working now, I added default views to the contentresolver like :
<property name="defaultViews">
<list>
<!-- JSON View -->
<bean
class="org.springframework.web.servlet.view.json.MappingJacksonJsonView">
</bean>
<!-- JAXB XML View -->
<bean class="org.springframework.web.servlet.view.xml.MarshallingView">
<constructor-arg>
<bean class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
<property name="classesToBeBound">
<list>
<value>com.chodak.tx.model.User</value>
</list>
</property>
</bean>
</constructor-arg>
</bean>
</list>
</property>
and removed the getUser method, the one annoted to produce xml and json. If I leave it with the added default views its still not working. If anyone can explain why it would be awesome :)
You can do
import org.springframework.http.MediaType;
import org.springframework.web.servlet.config.annotation.ContentNegotiationConfigurer;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
#Configuration
// #EnableWebMvc already autoconfigured by Spring Boot
public class MvcConfiguration {
#Bean
public WebMvcConfigurer contentNegotiationConfigurer() {
return new WebMvcConfigurerAdapter() {
#Override
public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
configurer.favorPathExtension(false)
.favorParameter(true)
.parameterName("mediaType")
.ignoreAcceptHeader(true)
.useJaf(false)
.defaultContentType(MediaType.APPLICATION_JSON)
.mediaType("xml", MediaType.APPLICATION_XML)
.mediaType("json", MediaType.APPLICATION_JSON);
// this line alone gave me xhtml for some reason
// configurer.defaultContentType(MediaType.APPLICATION_JSON_UTF8);
}
};
}
(tried with Spring Boot 1.5.x)
see https://spring.io/blog/2013/05/11/content-negotiation-using-spring-mvc
"What we did, in both cases:
Disabled path extension. Note that favor does not mean use one approach in preference to another, it just enables or disables it. The order of checking is always path extension, parameter, Accept header.
Enable the use of the URL parameter but instead of using the default parameter, format, we will use mediaType instead.
Ignore the Accept header completely. This is often the best approach if most of your clients are actually web-browsers (typically making REST calls via AJAX).
Don't use the JAF, instead specify the media type mappings manually - we only wish to support JSON and XML."

Does order matter while injecting properties in ProxyFactoryBean

I am trying to inject the aspects in a service. For this service I am creating a proxied object using classic way.
I have written a bean- baseProxy of type (ProxyFactoryBean) which contains a list of all the required advices.
<bean id="baseProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="interceptorNames">
<list>
<value>methodInvocationAdvice</value>
</list>
</property>
</bean>
I am creating a proxy for the service like this :
<bean id="singproxy" parent="baseProxy">
<property name="target" ref="singtarget" />
<property name="targetClass" value="com.spring.learning.SingingService"></property>
</bean>
Which doesn't work but when I revert these two properties and write like this :
<bean id="singproxy" parent="baseProxy">
<property name="targetClass" value="com.spring.learning.SingingService"></property>
<property name="target" ref="singtarget" />
</bean>
To my surprise it works fine. In spring does it matter on the order for bean ? Or its a special case with ProxyFactoryBean?
I tried with Spring 3.0 I am not sure same behavior exists with previous versions.
Concerning target and targetClass, It's one or the other, but not both. Here's the relevant source (from org.springframework.aop.framework.AdvisedSupport), a parent class of ProxyFactoryBean:
public void setTarget(Object target) {
setTargetSource(new SingletonTargetSource(target));
}
public void setTargetSource(TargetSource targetSource) {
this.targetSource = (targetSource != null ? targetSource : EMPTY_TARGET_SOURCE);
}
public void setTargetClass(Class targetClass) {
this.targetSource = EmptyTargetSource.forClass(targetClass);
}
As you can see, both setTarget() and setTargetClass() write to the same field, so the last assignment wins.

Is there a shorter version of how you use MethodInvokingFactoryBean in cfg file?

Currently it is used as shown below...wondering if there is a shorter version (similar to the util namespace)
<bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="targetObject">
<ref bean="transformation" />
</property>
<property name="targetMethod">
<value>addTransformers</value>
</property>
<property name="arguments">
<list>
<ref bean="customTransformers" />
</list>
</property>
</bean>
You can write it a bit shorter by using Spring P-Namespace
You're using very verbose syntax, you can make it shorter just by being more concise:
<bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="targetObject" ref="transformation"/>
<property name="targetMethod" value="addTransformers"/>
<property name="arguments">
<list>
<ref bean="customTransformers" />
</list>
</property>
</bean>
Aside from that, and maybe using the p: syntax mentioned by #Ralph, I'm not aware of a namespace-based shortcut.
Another approach using #Configuration but for setting a System property, you can adapt though:
#Bean
public Properties retrieveSystemProperties(){
return System.getProperties();
}
private Properties systemProperties;
public Properties getSystemProperties() {
return systemProperties;
}
#Resource(name="retrieveSystemProperties")
public void setSystemProperties(Properties systemProperties) {
this.systemProperties = systemProperties;
}
#Bean
public MethodInvokingFactoryBean methodInvokingFactoryBean() {
MethodInvokingFactoryBean methodInvokingFactoryBean = new MethodInvokingFactoryBean();
methodInvokingFactoryBean.setStaticMethod("java.lang.System.setProperties");
systemProperties.setProperty("http.keepAlive", "false");
methodInvokingFactoryBean.setArguments(new Object[]{systemProperties});
return methodInvokingFactoryBean;
}
If you don't have any parameters, you can do this:
<bean id="mybean" factory-instance="otherBean" factory-method="getMyBean"/>

Resources