We are using Spring 1.2.9 and we are not able to use map:util
Here is the constructor of code which i have to unit test,
public ViewAction() {
screen = Collections.synchronizedMap(new HashMap());
tab = Collections.synchronizedMap(new HashMap());
}
How can i inject the hashmap and add values to the hashmap in the configuration xml.
NOTE : THE QUESTION IS NOT ABOUT USING HASHMAP. IT IS ABOUT CONFIGURING THE xml file. I tried the following and failed
<bean name="viewactionbean" class="com.test.helper.web.ViewAction">
<property name="screen">
<map>
</map>
</property>
</bean>
Error while i configure the above XML file is,
BeanCreationException: Error creating bean with name 'viewactionbean' defined in class path resource
NOTE : Since i am using Spring 1.2.9, i am not able to use "map:util"
You can solve your problem in two different ways:
You can use synchronized(screen) blocks everywhere you need to access anything in the screen map. That way you don't really need a synchronizedMap as you are already guarding your code anytime you access it.
You can set the synchronizedMap in the setter of your bean, so when Spring injects it you are placing a wrapper around it instead the actual instance provided by Spring:
Example setter method:
public void setScreen(Map screen) {
this.screen = Collections.synchronizedMap(screen);
}
Problem with this last approach is that if you need to perform two or more operations in the map inside a single method in your bean, you still need the synchronized(screen) block to protect from race conditions.
To configure the map in spring you should be able to do this:
<bean id="..." class="....">
<property name="screen">
<map>
<entry key="myKey" value="myValue" />
</map>
</property>
</bean>
You have to use something like this for HashMap.
private static Map<K,V> screen = Collections.synchronizedMap(new HashMap<K,V>);
Than for Thread safety you can use .
synchronized (screen) {
}
Related
SpringMVC comes with a 'mvc' namespace handled by (unsurprisingly) 'MvcNamespaceHandler', defined like this :
public class MvcNamespaceHandler extends NamespaceHandlerSupport {
public void init() {
registerBeanDefinitionParser("annotation-driven", new AnnotationDrivenBeanDefinitionParser());
registerBeanDefinitionParser("default-servlet-handler", new DefaultServletHandlerBeanDefinitionParser());
registerBeanDefinitionParser("interceptors", new InterceptorsBeanDefinitionParser());
registerBeanDefinitionParser("resources", new ResourcesBeanDefinitionParser());
registerBeanDefinitionParser("view-controller", new ViewControllerBeanDefinitionParser());
}
}
I would like to modify the behavior of the namespace so that mvc:resources element are handled by a custom ResourcesBeanDefinitionParser (in my case, to replace a ResourcesHttpRequestHandler, create by the bean definition parser, with a custom implementation).
I would like to know if it is possible to do that whithout going through the hassle of creating a brand new namespace (as described here http://static.springsource.org/spring/docs/2.0.x/reference/extensible-xml.html).
Thanks !
You can create a custom namespace to register a different ResourceHttpRequestHandler, but like you have said, it is definitely a good amount of work.
A better approach may be to simply define the bean explicitly in configuration this way, the ResourcesBeanDefinition essentially does this:
<bean name="resourceHandler" class="org.springframework.web.servlet.resource.ResourceHttpRequestHandler">
<property name="locations">
<list>
<value>/resources/</value>
</property>
</bean>
<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="urlMap">
<map>
<entry key="/resources/**" value-ref="resourceHandler"/>
</map>
</property>
</bean>
You can simply replace the resourceHandler with your implementation here.
I've had this very same issue today (but for the context namespaceHandler). I've done it on a hacky way.
create a file named spring.handlers in your META-INF folder and put a declaration overriding the default schema. In your case, something like this:
http\://www.springframework.org/schema/mvc=org.springframework.web.servlet.config.MvcNamespaceHandler
for
http\://www.springframework.org/schema/mvc=YOURBEANPATH.
Perhaps you will need to declare the spring.handlers file inside a jar with a name that starts with a letter greater than 's' (in my case it was 't'), as spring will merge the spring.handlers definitions by the order they are found.
For debugging information, take a look at DefaultNamespaceHandlerResolver#getHandlerMappings.
Just a quick question: In an OOP MVC application, one key principle is the seperation of responsibilities. I therefor think that a model and the object that fetches the model from a database, file, xml, webservice, etc. should be seperated from the model itself. This can for example be done by implementing a datamapper.
However, what do I do when I have a model that can be loaded from different sources? Should the model be in charge of the datasource, or is this the responsibility of the controller?
An simple example could be a config class that can be loaded from a database or a file. Should the controller instruct the datasource, or should the model know when to load the config info from a database or a file?
have used frameworks were the datasource is informed by the controller MachII, Model-Glue (Coldfusion frameworks) and also from the model layer (ColdSpring) - like Spring in Java.
I think the key thing is to use what makes more sense to you, keep the coupling to a minimum and be consistent, meaning don't put datasource or object dependencies in multiple places.
You could also consider using a service type object to abstract the datasource and have it serve either who it likes.
That IOC file could look like this:
<?xml version="1.0" encoding="UTF-8"?>
<beans>
<bean id="chartShareObj" class="model.charts.ChartShared" autowire="byType" />
<bean id="trendChartObj" class="model.charts.TrendChart" autowire="byType" />
<bean id="adminRightsDA0" class="org.datamentor.institution.RightsDAO">
<constructor-arg name="dsn">
<value>${dsn_dm}</value>
</constructor-arg>
</bean>
<bean id="assessmentManager" class="model.assessment.Manager">
<constructor-arg name="dsn">
<value>${dsn_au}</value>
</constructor-arg>
</bean>
</beans>
You can see the different datasources specified by args via args defined in a controller.
Based on your situation and response I would suggest looking into dependency injection. You can then let it handle determining which data source to use based on whatever set of variables you want to let it determine things by. This is what I use when I have multiple data sources and want to have the data source determined by some predetermined factors I have chosen.
http://en.wikipedia.org/wiki/Dependency_injection
As to who should handle the injection, I leave that to a repository factory and simply ask for an interface in the controller. The factory then determines based on the dependency injection which repository to provide.
Example:
Dependency Injection in an global Infrastructure class:
Bind<INewsArticleRepository>().ToMethod(context => NewsRepositoryFactory.Create((NewsRepositoryFactory.RepositoryType)Enum.Parse(typeof(NewsRepositoryFactory.RepositoryType), ConfigurationManager.AppSettings["NewsArticleRepositoryProvider"])));
Repository Factory
public static INewsArticleRepository Create(RepositoryType type)
{
switch (type)
{
case RepositoryType.Mock:
return new MockNewsArticlesRepository();
case RepositoryType.Sql:
return new SqlNewsArticleRepository();
default:
throw new NotImplementedException();
}
}
Call in the controller for a repository
private INewsArticleRepository newsItemRepository;
public NewsController(INewsArticleRepository newsItemRepository)
{
this.newsItemRepository = newsItemRepository;
}
They way I do it in Coldbox is using CB's INJECT method in the model. In the cfargument of the constructor, I specify:
<cfargument name="dsn" type="any" inject="coldbox:datasource:dsn">
And that's from specifying the dsn in the coldbox.cfc file, and calling it "dsn". I keep it generic so I can copy this stuff to other projects and only have to change the DSN name in the coldbox.cfc.
But then after doing that, you get the dsn like this:
variables.dsn = arguments.dsn.getName();
I hope this helps, at least a little.
Rob
I am using groovy-grails with jasper reports to develop an app. I need to lookup 'report bean' based on its parameter (like reportname /id retrived from database, which I will get from customer click) - which will be stored as a property of report bean from resources.xml into either the reportcontroller or reportservice. Also I have to 'get' the jrxml template related to this id and the parameter Map, both defined as properties in the bean. I need to know like how can we achieve this and do we need to define any 'managing beans' in the xml which manage these report beans.
So for example the report bean will look like as follows:
<bean id="DeptReport" class="com.myapp.reporting.domain.Report">
<property name="reportName" value="Dept Report"/>
<property name="reportFiles">
<map>
<entry key="JasperPrint" value="DeptRoles.jrxml"/>
</map>
</property>
<property name="promptforparameter" value="true"/>
<property name="parameter" value="department_id"/>
<property name="displayName" value="report.deptReport.name"/>
</bean>
There will be many beans like this.
Also the .jrxml file for all reports are stored in a directory and I want to wire that location into the reporting context so that whenever a report is clicked on the front end I want to look up these values from the context into the report service/controller to generate the report. I know we have to do like a ctx.getbean(reportId) somewhere but I also want to know how to setup a manager bean with some other properties like template location, datasource, parameter map, reportid and a jasperreportrenderrer object. So this ReportManager bean is loaded reused every time there is a call for another report and persisted across a user session ideally.
You should be able to do something like this:
import org.springframework.context.*
class MyService implements ApplicationContextAware {
ApplicationContext applicationContext
def getBeanByName( String name ) {
applicationContext.getBean( name )
}
}
That's in a grails Service class, but the same should hold true for a controller
In a Spring 3 based web (portlet) application I have a controller with a method like this:
#RenderMapping
public ModelAndView handleRenderRequest(...,#RequestParam MyClass myObject)
{
...
}
Now I wonder: How do I tell spring how to convert the request parameter to MyClass. I found information about property editors and about the Converter interface and there seem to be some implications that Converter is the successor of the property editor, but nobody seems to like being explicit about it.
I implemented the converter interface for String to MyClass conversion. But how do I tell Spring about it? I am using annotation based configuration wherever possible, so I checked whether spring will detect the Converter from my classpath automatically, but it does not.
So thought that the part Configuring a ConversionService from the manual wants to tell me that I've got to add the following to my applicationContext.xml which I did:
<bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
<property name="converters">
<list>
<bean class="some.package.MyConverter"/>
</list>
</property>
</bean>
Bit still:
org.springframework.beans.ConversionNotSupportedException: Failed to
convert value [...]
So what am I missing? And is there a way, to just configure a package and let spring scan this package for converters and register them automatically? And say that in one certain method I want to use a different converter than in all other methods. For example I want an integer that has a Luhn-Checksum to be checked and the checksum removed, how can I do that? Something like #RequestParam(converter=some.package.MyConverter.class) would be great.
EDIT
Ok, I just caught in the documentation:
Use the Formatter SPI when you're working in a client environment,
such as a web application, and need to parse and print localized field
values
So I guess that means I should use the Formatter SPI, yet a third possibility next to property editors and converters (I think I could really to with a comparison table or the like). I did implement the Parser interface as well and tried to register my converter using:
<bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
<property name="converters">
<set>
<bean class="some.package.SortOrderEnumConverterSpring"/>
</set>
</property>
</bean>
As you can see I used "set" instead of "list" for specifying the converters. I set a debugging breakpoint in the FormattingConversionServiceFactoryBean.setConverters method which did not fire upon using list, but it did fire on using set.
Additionally I added
<mvc:annotation-driven conversion-service="conversionService"/>
And the namespace for the mvc-prefix to my applicationContext. But still I get the conversion not supported exception.
I also tried going back to the converter approach and changed in my applicationContext.xml file the parameter list for converters from list to set, but that did not change anything either.
EDIT2
As digitaljoel pointed out it is possible to set different converters per controller using an initBinder method. I applied this to my controller:
#Autowired
private ConversionService conversionService;
#InitBinder
public void initBinder(WebDataBinder binder)
{
binder.setConversionService(conversionService);
}
And in my applicationContext.xml:
<bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
<property name="converters">
<set>
<bean class="some.package.with.MyConverter"/>
</set>
</property>
</bean>
And all suddenly the conversion works just fine :-). But I am not quite happy about having to apply this to each and every of my controllers. There must be a way to just set it in my applicationContext for everyone, is there not? Good to know that I can override default if I need to (after all I asked for that), but I still want to set defaults.
And what about the Formatter stuff. Shouldn't I be using that instead of Converter?
Spring Portlet MVC 3.0 does not support
<mvc:annotation-driven conversion-service="conversionService"/>
Visit https://jira.springsource.org/browse/SPR-6817 for more info about this.
However you can add this to your common applicationContext
<bean
class="org.springframework.web.portlet.mvc.annotation.AnnotationMethodHandlerAdapter">
<property name="webBindingInitializer">
<bean
class="org.springframework.web.bind.support.ConfigurableWebBindingInitializer">
<property name="conversionService">
<list>
<ref bean="conversionService" />
</list>
</property>
</bean>
</property>
</bean>
This way you do not need add #InitBinder to every single controller
and of course
<bean id="conversionService"
class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
<property name="converters">
<list>
<!-- converter implementations here -->
</list>
</property>
</bean>
You are correct that Converter (and ConverterFactory) are the successors to property editors. Your problem may be that you are not accepting the appropriate type as a parameter to your converter, but that's hard to say without seeing the converter code. If you are expecting Long or Integer you may actually be getting a String from Spring and need to perform that key conversion yourself first.
As for configuration, I believe you need to list all of your converters in the bean configuration in your xml. If you annotate your converter implementation with #Component you might be able to reference it by the bean name instead of the fully qualified path, but I have only tried that for a ConverterFactory, not a Converter.
Finally, on specific converters, it looks like you may be able to configure the conversion service at the controller level (see Javi's answer on Setting up a mixed configuration for annotation-based Spring MVC controllers ) and then you could just place that method (and others that require that controller) into a controller that uses a secondary conversion service which you ought to be able to inject by name with the #Resource annotation.
Implement a WebArgumentResolver:
public class MyArgumentResolver implements WebArgumentResolver
{
#Override
public Object resolveArgument(MethodParameter methodParameter,
NativeWebRequest webRequest) throws Exception
{
Class<?> paramType = methodParameter.getParameterType();
if (paramType == MyClass.class)
{
String parameterName = methodParameter.getParameterName();
String stringParameter = webRequest.getParameter(parameterName);
return convert(stringParameter);
}
return UNRESOLVED;
}
}
And register it in your applicationContext.xml:
<bean class="org.springframework.web.portlet.mvc.annotation.AnnotationMethodHandlerAdapter">
<property name="customArgumentResolver">
<bean class="com.dshs.eakte.util.MyArgumentResolver" />
</property>
</bean>
This works and even has the advantage of allowing parameter conversion that is based on multiple method parameters.
To achieve something similar to what you're doing, I found this blog entry useful.
i think you need to use something like
public ModelAndView handleRenderRequest(...,#ModelAttribute("myObject") MyClass myObject)
I am new to Spring DI and i am implimenting DI for the first time in my webapplication.
it seems i am doing somehing wrong and it related the way i am using spring scope.here is my problem
i have a serive class where i am injecting various other object in order to achieve the desired functionality
here is my spring file entries
<bean id="ImportServiceImpl" class="ImportServiceImpl" factory-method="getInstance">
<property name="browseDirectory" ref="browseDirectoryImpl"/>
<property name="xmlUnmarshaller" ref="xmlUnmarshallerImpl"/>
<property name="Adaptar" ref="AdaptarImpl"/>
<property name="DAOService" ref="DAO"/>
</bean>
<bean id="browseDirectoryImpl" class="BrowseDirectoryImpl" factory-method="getInstance" />
<bean id="xmlUnmarshallerImpl" class="XMLUnmarshallerImpl"/>
<bean id="AdaptarImpl" class="AdaptarImpl" factory-method="getInstance"/>
now in my adaptarImpl class i have a refrence to some other object which is being initialized in the constructor
private AdaptarImpl(){
foo=new Foo();
}
now for the first time when the server start and this service run fist time everything is fine foo is being initilized to its proper initialization value but for all other subsequent calls Spring is returing refrence to the previous initialized foo object where i want that for each new request a new instance of foo should be created.
it apperas to me that the factory method being used in the above code factory-method="getInstance"
is being called only once when server called and all other subsequent calles returning same refrence where i want a new instance for every request.
here is my facory method
public static ImportServiceImpl getInstance(){
return new ImportServiceImpl();
}
i know i am doing basics wrong in DI but not sure where it is.I am using Struts2 for MVC and for service layer using Spring DI
any help in this regard will be helpful
Thanks
Umesh
I'm not sure I understand your question, but it sounds like you ought to ask Spring to inject the reference to Foo into your AdapterImpl and make its scope "request". If you need Spring to control object creation, don't call "new".
I think you need to look at
http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/beans.html#beans-factory-scopes
and look at table 3.3.