I've been looking and toiling most of the day trying to get something to work. Here's the situation:
The Situation
I am working on an audit-trail for a tool we have at work; this tool is used to edit info (such as texts on websites). Right now everything works fine, but there's one teeny issue:
Right now I am storing the user-data (username, password, ipAddress) in a #context-info (MSSQL). This works fine whenever one user is logged in at a time, but this rarely happens
Example:
I log on
I edit stuff
Stuff I edited gets logged under my name
Someone else logs into the system
Stuff I edit is logged under this other user's name, instead of my own, because the #context-info changed at login.
The Solution
A Session-scoped bean that stores local session-data and then passes parameters per Database Query to the Context info through an Interceptor.
What have I done so far
I am currently following this guide: Spring Bean Scopes - Tutorialspoint for the purpose of getting a Session-scoped bean. I have the following defined in my support-servlet.xml (this is where we define beans):
<!-- Session Beans -->
<bean id="helloWorld" class="com.lcmg.ticket.support.service.HelloWorld" scope="session">
</bean>
The .java files have been taken from the tutorial, and work up to a certain point. For instance:
ApplicationContext context = new ClassPathXmlApplicationContext("support-servlet.xml");
Gave me issues, untill I changed the parameter to
("classpath*:support-servlet.xml")
And then this happened..
The problem
The problem lies herein:
HelloWorld hwA = (HelloWorld)context.getBean("helloWorld");
If I debug and step over this line, I get a No bean named 'helloWorld' is defined exception thrown at my face as soon as I log into the tool. I have googled, tinkered, and fiddled and now at the end of the day I still have no solution.
So the question is:
How do I get this session-bean to work?
I hope I have provided sufficient information, but do not hesitate to ask if you need more information.
So I fiddled around some more and I did this:
The bean definition has been moved to a different .xml (we apparantly had applicationContext.xml with other scope="session" beans, it now looks like this (I've also changed the name for the implementation etc.):
<bean id="auditUser" class="com.lcmg.ticket.support.service.model.AuditUser" scope="session">
</bean>
I dumped the whole applicationContext context.. bit, and instead mapped the bean to a class-bean, like so:
<bean name="/historyList" class="com.lcmg.ticket.support.web.controller.HistoryListController">
/*Other-for-this-example-useless properties*/
<property name="auditUser" ref="auditUser"/>
</bean>
And I could then in my code make a variable auditUser, create a setter, and then I did this:
auditUser.setSessionUser(sessionUser);
auditUser.setPassword(command.getPassword());
And now it works. No more errors, and whenever I call something from auditUser it's the same throughout the session.
Related
Currently in my project the datasource , transactionmanager and other bean required for database connectivity are defined in xml file and there values are configured in property file from which it takes to do the connection.
for ex:
<bean id="DataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
destroy-method="close" p:driverClass="${DRIVER_CLASS}" p:jdbcUrl="${DB_URL}"
p:minPoolSize="${MIN_DB_POOL_SIZE}" p:maxPoolSize="${DB_POOL_SIZE}"
p:maxStatements="${DB_POOL_SIZE}" p:idleConnectionTestPeriod="${IDLE_CONNECTION_TEST_PERIOD}"
p:loginTeimeout="${LOGIN_TIMEOUT}" scope="singleton"></bean>
ALL these like values ${DB_POOL_SIZE} are configured in property file.
the class com.mchange.v2.c3p0.ComboPooledDataSource is final class and can't be extended. so my requirement is
:when spring create the bean of Datasource i should be able to set the value of the variable in xml(DB_URL) from my java file through setter method.
how to do that?
I don't quite get what you are trying to do, but if your problem is that you'd like to extend ComboPoolDataSource with some custom functionality, just extend AbstractComboPooledDataSource. Check out the source to ComboPooledDataSource. There's not much there (once you get past the annoying copyright header). Use that as a template, and extend AbstractComboPooledDataSource however you'd like.
I have a web controller which I configure in the controller-config.xml using
<mvc:annotation-driven />
<context:annotation-config />
<context:component-scan base-package="com.ecommerce.web.controller" />
The controller has the #Controller annotation like below.
#Controller
public class HomeController
I have included the #Autowired annotation on the dependencies, but when I first start up the application I am unable to set any properties on the wired objects.
For example, I have a storeProfile object which when in debug mode I see has multiple properties set as it should.
But, when I try to set one of the storeProfile properties on an #Autowried bean it is still null or empty string!?
If you look at the attached images it shows that after I step past the line this.storeProfileContext.setStoreProfile(storeProf ile) the debugger still shows the storeProfile property as null
Actually, there are a couple dependencies which look like they are created (they are not null and the application functions), but I am unable to set anything on these objects.
I asked the same question on the Spring forums too - hoping to get this figured out.
Thanks so much!
That is because you are looking at the fields of the proxy, which gets created when you have <aop:scoped-proxy/>, if you invoke your getter for the set values, you should see the correct values retrieved from the proxied object.
The instances you are examining are CGLIB proxies.
CGLIB subclasses your beans, delegating all method invocations to the target beans.
So the fields of the super classes are still present but not used.
I've a doubt about Spring session bean. Let me try to explain what I need and what I did. I need to store on a session variable (in that case a Bean) the user_id so, when I need to create some record on db I can keep track of who did what.
To do that, for first, I created a bean and, second, I modified my application context in that way:
<bean id="UserInfo" class="net.agdev.session.UserInfo" scope="session">
<aop:scoped-proxy/>
</bean>
I read that using this :
ContextLoader.getCurrentWebApplicationContext().getBean("UserInfo");
is ppossible to access to the bean, but it's not yet clear how to fill that bean..
I tryed to read on Spring documentation how to initalize the bean and how to recall on my Class controller but I didn't find anything.
Could you suggest where to find an example or a tutorial to do that?
many thanks!
Andrea
You mean how to get the user_id into the session bean? Depending on your application this should probably happen right after the user "logged in". Meaning, if you for instance have a login webflow or controller, set the user_id in your session bean within that webflow or controller.
So if I understood your context correctly this has only very little to do with Spring itself and mostly with your application :-)
If you want other aspects of your bean initialized for instance from operations on other services you could set an init-method on the bean definition as detailed here.
By aspect programming like AspectJ. You have to set some trigger, for example after an user does something you have to read your bean and fill it the operation info that have been performed by the user.
You can use #annotation to define trigger or you can do it by spring xml file. I think you have to use an application context bean and not a session bean.
I have a method in a controller:
public FormValidationResult submitFormAndSendEmail(#Valid ContactForm form, BindingResult result,
#HttpSessionParam(value = "lastTimeContactFormSent", required = false) Calendar lastTimeContactFormSent)
As you can see I have created a #HttpSessionParam annotation, this will take a variable from the HttpSession and put it into the specified method parameter.
However...
Before the argument is being resolved, I recieve an InstantiationExceptionConstructorAccessorImpl because calendar cannot be instantiated by a default constructor.
Using the given stacktrace, I see that the HandlerMethodInvoker within "resolveModelAttribute" is causing the instantiation.
How can i prevent this? I don't want an instantiation, I want to use my own WebArgumentResolver in order to fill the method parameter.
Any clues?
More info:
Stacktrace by Spring (3.0.4):
java.lang.InstantiationException
at sun.reflect.InstantiationExceptionConstructorAccessorImpl.newInstance(InstantiationExceptionConstructorAccessorImpl.java:30)
at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:126)
at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:104)
at org.springframework.web.bind.annotation.support.HandlerMethodInvoker.resolveModelAttribute(HandlerMethodInvoker.java:772)
at org.springframework.web.bind.annotation.support.HandlerMethodInvoker.resolveHandlerArguments(HandlerMethodInvoker.java:356)
at org.springframework.web.bind.annotation.support.HandlerMethodInvoker.invokeHandlerMethod(HandlerMethodInvoker.java:171)
at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.invokeHandlerMethod(AnnotationMethodHandlerAdapter.java:427)
at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.handle(AnnotationMethodHandlerAdapter.java:415)
I don't see the debugger hit the webargumentresolver.
The argument is defined in my application context (xml) as following:
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
<property name="customArgumentResolver" ref="sessionParamResolver"/>
</bean>
<!-- annotation to resolve httpSession attributes -->
<bean id="sessionParamResolver" class="nl.usgpeople.vakgilde.spring.mvc.extensions.SessionParamArgumentResolver"/>
It looks like your argument resolver wasn't fired or didn't resolved the argument. Make sure that:
your resolver is correctly passed to AnnotationHandlerMethodAdapter
if your resolver is fired, it correctly resolves the argument
Looks like axtavt was right, partially. The WebArgument did not get resolved. However, it was defined in the context xml properly. So why did'nt it work?
The application-context.xml included an mvc-context.xml , (using the import tag). Within the mvc-context.xml I had defined the bean and such.
Moving the bean definition outside mvc-context.xml , above the import tag, made Spring 'notice' the bean and resolve in the appropriate order.
Looking further, it looks like as long as my sessionParamResolver bean is defined above the tag, it works. When placing my bean below this tag, it does not work.
Looking at the Spring documentation, at chapter 15.12 Configuring Spring MVC , it is said that it will define a AnnotationMethodHandlerAdapter. So I guess defining it beforehand makes sure it also uses your customArgumentResolvers.
<bean id="data.emf"
class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean" >
<property name="persistenceUnitName" value="transactions-optional" />
</bean>
from what i know by default all bean are singleton (according to document) but i somehow still getting duplicated creating of entitymanagerfactory. is there any parameter i can set for bean above in spring 3.0 to force singleton? the problem only appear in gae production, on hosted mode, no problem
You can force a bean to be a singleton like this:
<bean scope="singleton" ... >
</bean>
You generally don't need to do this, however, since singleton is the default scope, and there's no way to change the default.
The Spring DEBUG-level logs will generate entries every time a bean is instantiated, so have a look through there to see when and where your bean is being processed.
Maybe the problem doesn't come form the scope. Are you sure you haven't defined another bean in anther place of the program (for example with an annotation) or in another context file? Comment that bean definition and try if it can find a instance of it without declaring it here.