I really need your help. I'm using my portlet app as usual when suddenly I have to get out of computer. When I return, there's NullPointerException. OK, why's that? Hmm... my session doesn't contain object it should hold. So, I'm probably loosing something but here's how I always looked at SessionAttributes.
I have my Controller annotated as so:
#SessionAttributes({
SOME_ATTR
})
Then I have a method with following signature:
#Valid #ModelAttribute(SOME_ATTR) SomeObject someObject
And also init method for my session attribute:
#ModelAttribute(SOME_ATTR)
public SomeObject getSomeEmptyObject() {
return someUtils.createSomeObject();
}
When I debugged my app at this point I found out that:
manually looking into the session, there's nothing in it
form is properly binded to someObject
So my two big questions are:
why doesn't Spring set someObject into session as well?
when the session was invalidated, why wasn't getSomeEmptyObject() called to fill the empty space?
Thanks in forward!
Have a look at HttpSessionBindingListener and the HttpSessionAttributeListener. If SomeObject is a class that you control, you can implement HttpSessionBindingListener otherwise you will likely need HttpSessionAttributeListener.
This SO posting covers this pretty well.
Well, do you set your session attribute in proper form:
#SessionAttributes(value = {"user", "register"})
Thats all that I can think about.
Related
On an XPage I have placed a checkbox group:
<xp:checkBoxGroup
value="#{employeeBean.employee.concern}"
disabled="#{employeeBean.employee.editable eq false}">
<xp:selectItem itemLabel="yes"></xp:selectItem>
<xp:selectItem itemLabel="no"></xp:selectItem>
<xp:selectItem itemLabel="maybe"></xp:selectItem>
</xp:checkBoxGroup>
I have binded the value of the control to field in my Proposal class via a managed bean.
The field concern is of type string and has its out of the box getters and setters.
The problem is whenever I include the data-binding and change values the complete XPage SSJS fails. I do not get an error in the console (server, web client).
Does this have something to do with the type of value the checkbox returns or should I change the type of field in my class?
One thing that springs to mind is the employee object. If this is not set (i.e. there is an instance of the object) then it will fail with a null pointer exception.
In your case it is quite valid the concern field is of type String - obviously you will need a getConcern() and setConcern(String value) method.
Now the real problem is that you cannot see what the server thinks is wrong!
The best way to get to that is to look at the stack traces in the logs. And by far the easiest way to do that is to install the "XPages Log File Reader" application from OpenNTF.org
But my guess is that you haven't created an employee object prior to calling the getEmployee() method to return it ;-)
/John
in my controller, I need to choose what service implementation I need to use on spring. Before I was encapsulating this code in a factory, but I think that its not a good practice...
#Component
public class StoreServiceFactory {
#Autowired
private List<StoreService> storeServices;
public StoreService getService(){
if(isActiveSale){
return storeServices.get("PublicStoreService")
}
return storeServices.get("PrivateStoreService")
}
}
So I would like to encapsulate this behaviour to not care about inside my controller.. How can I get it??
If isActiveSale changes when the application is running, I think that what you got is a good solution. Since the Controller is a singleton you can't expect a different injection everytime this value changes.
If you get the value only on the startup of the application(e.g. from some property) you can use a profile.
There is nothing wrong with a factory, although as #R4J points out in the comments it is more of a provider, since it doesn't instantiate anything. I would consider the factory/provider a good choice if the 'isActiveSale' status changes based on things outside of the current control flow, like a configuration in a property file. A setting set in some adminstration screen, or maybe based on the time of day.
I'm querying a DB in this EJB. Result is Iterable (I can't change that).
But since the EJB is #Stateless it will "reuse" the Iterable<>, and the query result just gets added to it. Instead of being a "new" one!
How could i avoid that ?
I don't know if there a "fix" on the Iterable or is there something to be done with the SessionBean? Is this a bad combination?
#Stateless
public class StartSessionBean implements Serializable, StartSessionBeanLocal {
...
public Iterable<VType> resultQuery;
...
public List<VType> queryThis(String this) {
...
resultQuery = (Iterable<Type>) "query DB";
//Do Things here
return something;
}
}
You cannot maintain state such as public Iterable<VType> resultQuery; in a stateless session bean. That is what "stateless" means.
In practice what actually happens varies from implementation to implementation. Some will give you a brand new bean each time you call it. Others will select one from a pool and give you that one, with the result that each client may get another's instance of resultQuery.
If you want to maintain state in the EJB then you must use a #Stateful session bean.
Edit: You should not need to maintain the resultQuery field anyway. Just make it a local in your method implementation. Presumably you're using it in a for-each loop as that is what they're for.
I have been wrestling with this problem for a while. I would like to use the same Stripes ActionBean for show and update actions. However, I have not been able to figure out how to do this in a clean way that allows reliable binding, validation, and verification of object ownership by the current user.
For example, lets say our action bean takes a postingId. The posting belongs to a user, which is logged in. We might have something like this:
#UrlBinding("/posting/{postingId}")
#RolesAllowed({ "USER" })
public class PostingActionBean extends BaseActionBean
Now, for the show action, we could define:
private int postingId; // assume the parameter in #UrlBinding above was renamed
private Posting posting;
And now use #After(stages = LifecycleStage.BindingAndValidation) to fetch the Posting. Our #After function can verify that the currently logged in user owns the posting. We must use #After, not #Before, because the postingId won't have been bound to the parameter before hand.
However, for an update function, you want to bind the Posting object to the Posting variable using #Before, not #After, so that the returned form entries get applied on top of the existing Posting object, instead of onto an empty stub.
A custom TypeConverter<T> would work well here, but because the session isn't available from the TypeConverter interface, its difficult to validate ownership of the object during binding.
The only solution I can see is to use two separate action beans, one for show, and one for update. If you do this however, the <stripes:form> tag and its downstream tags won't correctly populate the values of the form, because the beanclass or action tags must map back to the same ActionBean.
As far as I can see, the Stripes model only holds together when manipulating simple (none POJO) parameters. In any other case, you seem to run into a catch-22 of binding your object from your data store and overwriting it with updates sent from the client.
I've got to be missing something. What is the best practice from experienced Stripes users?
In my opinion, authorisation is orthogonal to object hydration. By this, I mean that you should separate the concerns of object hydration (in this case, using a postingId and turning it into a Posting) away from determining whether a user has authorisation to perform operations on that object (like show, update, delete, etc.,).
For object hydration, I use a TypeConverter<T>, and I hydrate the object without regard to the session user. Then inside my ActionBean I have a guard around the setter, thus...
public void setPosting(Posting posting) {
if (accessible(posting)) this.posting = posting;
}
where accessible(posting) looks something like this...
private boolean accessible(Posting posting) {
return authorisationChecker.isAuthorised(whoAmI(), posting);
}
Then your show() event method would look like this...
public Resolution show() {
if (posting == null) return NOT_FOUND;
return new ForwardResolution("/WEB-INF/jsp/posting.jsp");
}
Separately, when I use Stripes I often have multiple events (like "show", or "update") within the same Stripes ActionBean. For me it makes sense to group operations (verbs) around a related noun.
Using clean URLs, your ActionBean annotations would look like this...
#UrlBinding("/posting/{$event}/{posting}")
#RolesAllowed({ "USER" })
public class PostingActionBean extends BaseActionBean
...where {$event} is the name of your event method (i.e. "show" or "update"). Note that I am using {posting}, and not {postingId}.
For completeness, here is what your update() event method might look like...
public Resolution update() {
if (posting == null) throw new UnauthorisedAccessException();
postingService.saveOrUpdate(posting);
message("posting.save.confirmation");
return new RedirectResolution(PostingsAction.class);
}
I am new to jmock and trying to mock an HttpSession. I am getting:
java.lang.AssertionError: unexpected invocation: httpServletRequest.getSession()
no expectations specified: did you...
- forget to start an expectation with a cardinality clause?
- call a mocked method to specify the parameter of an expectation?
the test method:
#Test
public void testDoAuthorization(){
final HttpServletRequest request = context.mock(HttpServletRequest.class);
final HttpSession session = request.getSession();
context.checking(new Expectations(){{
one(request).getSession(true); will(returnValue(session));
}});
assertTrue(dwnLoadCel.doAuthorization(session));
}
I have done a bit of searching and it isn't clear to me still how this is done. Feels like I am missing some small piece. Anyone with experience in this can just point me in the right direction.
thanks
You don't need to mock the request object. Since the method you're testing (dwnLoadCel.doAuthorization()) only depends on an HttpSession object, that is what you should mock. So your code would look like this:
public void testDoAuthorization(){
final HttpSession session = context.mock(HttpSession.class);
context.checking(new Expectations(){{
// ???
}});
assertTrue(dwnLoadCel.doAuthorization(session));
}
The question becomes: what do you expect the SUT to actually do with the session object? You need to express in your expectations the calls to session and their corresponding return values that are supposed to result in doAuthorization returning true.
I think you need to tell the JMock context how many times you expect the method to be called before you actually go ahead and call it.
final HttpServletRequest request = context.mock(HttpServletRequest.class);
context.checking(new Expectations(){{
one(request).getSession(true); will(returnValue(session));
}});
final HttpSession session = request.getSession();
I'm not super familiar with JMock but do you actually care in your dwnLoadCel unit test how many times certain methods in the mocked object are called? Or are you just trying to test your class that depends on a HttpSession without an actual Session? If it's the latter than I think that JMock is overkill for you.
You might want to look into either creating a class that implements the HttpSession interface yourself for the purposes of unit testing only (a stub), and running your tests off of that, or you should take a look at dwnLoadCel and determine if it really needs to have a reference to the HttpSession, or if it just needs some properties within the HttpSession. Refactor dwnLoadCel to only depend on what it actually needs (a Map or a certain parameter value within the Session object) - this will make your unit test easier (the dependency on the servlet container goes bye-bye).
I think that you have some level of dependency injection in your class being tested already, but you might be dependent on too broad of an object. The Google Test Blog has had a lot of excellent articles on DI lately that you might find useful (I sure have).