I am new on using the Stripes framework and I need some help.
I want to call a method of an ActionBean from another ActionBean.
For example, I have two ActionBean:
#SessionScope
public class SessionActionBean extends AbstractActionBean{
private String property;
public void setUsername(String username) {
this.username = username;
}
}
And
public class TestActionBean extends AbstractActionBean {
...
public Resolution submitTest() {
//TODO Call setUsername is SessionActionBean
}
...
}
How do I call the setUsername of the SessionActionBean from TestActionBean? And if the SessionActionBean was not session scoped?
Thanks in advance
A few things:
If you want to store data in a user's session, #SessionScope isn't really what you want. You'd be better off extending ActionBeanContext and writing some getters and setters that store in context. See http://www.stripesframework.org/display/stripes/State+Management for more details.
If you really really want to use #SessionScope, make sure you read the caveat in the javadoc and make sure that's really what you need.
http://stripes.sourceforge.net/docs/current/javadoc/net/sourceforge/stripes/action/SessionScope.html
Since session scope ActionBeans are not generally encouraged by the
author, very few allowances will be made in Stripes to accommodate
session scope beans.
Finally, actually invoking methods from one action bean to the other is as simple as instantiating the bean and calling the method. It's kind of weird and backwards and the instantiated bean won't inherit Stripes context stuff, but you can do it.
If you'd rather have one #Resolution call another #Resolution, you can do that too: ForwardResolution(Class<? extends ActionBean> beanType).
Related
public abstract class Vehicle{
private String vehicleName;
public class Vehicle(String vehicleName){
this.vehicleName = vehicleName;
}
public void drive();
}
#Component("Car")
public class Car implements vehicle(){
public Car(String carName){
super(carName);
}
}
Here, My requirement is i want to set object name dynamically, i.e. as per above code, my reference to Car class is going to the name which i pass to #Component, and i want reference to Car class to be carName property from Car class.
Kindly suggest if it is possible or not.
Note - I dont want #Component name to be from any properties file, i want it from my existing car object.
According to your example, the short answer is 'NO'.
What you need to understand is #Component will creates a singleton bean, which will be initialized when the application context startup (unless you lazy initialize it). So you cannot really create a spring bean whenever you want.
Also note that these singleton beans should be stateless (only state they have is a shared state).
Since you haven't provide what is your real requirement, I suggest you to look at this bean scope documentation. It might be useful to you. Cheers!
The "#Component" is a Spring concept to create a reusable and injectable component to another (and whatever) Spring Bean.
It should not be used for a POJO.
#Component is to detect the custom beans, in your which is registering the component with Car as name, so as it is became a reference you are not allowed to change the Component name in runtime.
I am new to spring and saw this approach for resolving method parameter from properties file...
public void setUserDetails(#Value("${user.first.name}")String userName,
#Value("${user.address}") String address) {
this.userName = userName;
this.address = address;
}
but whenever i call this function the values are replaced by what i pass to function. i want to know how to call the function so that the values are fetched from properties file.
I am calling the function like...
setUserDetails("abc","xyz")
setUserDetails("abc",null)
setUserDetails(null,"xyz")
setUserDetails(null,null)
setUserDetails(null) // invalid
setUserDetails() // invalid
Everytime i get what i pass not from the data from properties. Please help to find me some solution or some reference link which may be helpful...
As mentioned on https://stackoverflow.com/a/21769581/679240, that annotation won't interfere on a manual invocation of the method; instead, it will automatically invoke the method right after instantiating the bean.
As the manual states:
Fields are injected right after construction of a bean, before any config methods are invoked. [...] Bean property setter methods [as in this case] are effectively just a special case of such a general config method.
Spring annotation works on bean creation, not during methods invocation. Suppose your class is called UserDetails:
#Component
public class UserDetails{
public #Value("${user.first.name}") String userName;
public #Value("${user.address}") String address;
}
I had just 1 implementation in my app that was using a certain class and its methods. I have added another implementation and turned on profiles. Adding a second profile made me implement that class for each profile separately, as there were some differences.
The problem is, that before the change I had that specific method invoked through Thymeleaf in html file as follows:
<td class="text-center" id="hashrate" th:text="${#findAndDisplayDataService.formatHashrate(networkHashrate.hashrate)}">Sample hashrate</td>
Now the name of the class has changed to:
FindAndDisplayDataServiceQuartz and FindAndDisplayDataServiceSpringScheduler accordingly to profiles. I'm not longer able to call the method in html file. I have wrapped both classes with an interface FindAndDisplayDataService, but I'm not really able to call interface method in Thymeleaf.
Make FindAndDisplayDataServiceQuartz and FindAndDisplayDataServiceSpringScheduler implement a common interface, possibly with same bean qualifier so you can autowire without worrying about bean names. Something like the below would do.
Define a common interface.
public interface FindAndDisplayDataService {
void formatHashrate(String hashrate);
}
Create profile specific bean definitions that extend the common interface.
#Component("findAndDisplayDataService")
#Profile("quartz")
public FindAndDisplayDataServiceQuartz implements FindAndDisplayDataService {
public void formatHashrate(String hashrate){
//do stuff based on quartz
}
}
#Component("findAndDisplayDataService")
#Profile("spring-scheduler")
public FindAndDisplayDataServiceSpringScheduler implements FindAndDisplayDataService {
public void formatHashrate(String hashrate){
//do stuff based on Spring scheduler
}
}
And in your thymeleaf template, You can inject any bean based on the #Component name findAndDisplayDataService.
You can create a UIService as a delegate, where you inject your FindAndDisplayDataService interface. That way you can call a concrete bean reference.
I have the archetype org.jboss.weld.archetypes:jboss-javaee6-webapp:1.0.1.CR2 and I try to understand the class MemberListProducer:
#RequestScoped
public class MemberListProducer
{
#Inject #MemberRepository private EntityManager em;
private List<Member> members;
#Produces #Named public List<Member> getMembers() {return members;}
public void onMemberListChanged(#Observes(notifyObserver = Reception.IF_EXISTS)
final Member member){
retrieveAllMembersOrderedByName();
}
#PostConstruct
public void retrieveAllMembersOrderedByName()
{
//Criteria Query to fetch all members
members = em.createQuery(criteria).getResultList();
}
}
The observer is invoked from another class with memberEventSrc.fire(newMember);, this seems clear: Once fired, the MemberListProducer updates the list of members.
But I don't understand why this is done in a #RequestScoped Bean. In my understanding the method retrieveAllMembersOrderedByName is anyway called by each request. Should this #Observes not be better placed in a #ViewScoped or #SessionScoped Bean? Does it have an effect in this case at all?
The use of #Observes there is more of an example than a real, practical use case. Consider the possibility of members changing before you render your response.
I don't think the website would work correctly if you removed it. Think about it like this:
When the request starts, the list of members is created and it contains all the members up to the moment of creation of this request scoped bean. Later, you persist a new member, so this list needs to be updated to render the response.
You think correctly when you say that the list is built for each request, however this happens at the beginning. After you add a member, you need to refresh it, don't you?
If this method weren't there, the response would be outdated (you'd render the list you had before you persisted the new member), and you would need one extra post or get to fetch the new list of members.
#Observes decouples listeners and event sources much like the observer pattern. So if the #Observes isn't there, you would need to explicitly add the new member to the list so that the response is correct.
I hope I understood your question correctly.
It's request scoped because it stores a list of members per request. If you need this list to be stored per-session, then change it.
But it looks wrong - you are discarding the member arguments of the observer method.
My problem is thus: I need a way to ensure only one given class can instantiate another. I don't want to have to make the other a nested inner class or something dumb like that. How do I do this? I forget offhand.
A private static inner class is exactly what you want. Nothing dumb about it.
public class Creator {
private static class Created {
}
}
Otherwise you can only protect instantiation on the package level.
public class Created {
Created() {
}
}
Which gives only classes from the same package access to the constructor.
Make the constructor private. Create a static factory method that takes an instance of the class that is allowed access. Have the factory method create a suitable object and use a settor on the object that is allowed access to the created object to give that class the created copy.
public class AllowedAccess
{
private SecureClass secure;
public setSecureClass( SecureClass secure )
{
this.secure = secure;
}
...
}
public class SecureClass
{
private SecureClass() {}
public static void Create( AllowedAccess allowed )
{
allowed.setSecureClass( new SecureClass() );
}
...
}
BTW, I'm suspicious of this design. Seems too highly coupled to me.
You could make the class that is to be protected from instantiation package private.
I agree with tvanfosson's answer and also with his comment about too high coupling. Why don't you retain more control of you class creation process by adopting an Inversion of Control framework like Spring or Guice?
IMHO creating classes with the "new" statement is to be considered a bit... obsolete, factories are to be preferred and IoC frameworks even more.
Regards