While making saveEventArgs.Cancel=true and returning from on saving event of content service is being redirected to #/content/content/edit/0, which is throwing request error in umbraco UI as there is no node with id 0.
Please help in understanding, how can I avoid umbraco to go to edit 0 id on saving cancel.
If anyone is looking for the specific answer. You call from within your Saving Event Handler the save method on IContentService and set the raise event to false.
E.g.
sender.Save(content, 0, false);
Related
Right now we are storing the session in map. So very first time , when we create session, it is possible that the session got created ,but due to some issue ,it immediately disconnected and logged out.
After some time, being the sessionId present in map, we are calling just lookup for that session and call logOn() . It should call my overridden logon() method which is not happening. Can anyone tell me the the possible clause and how to handle this ?when I see the logs, it's showing EndOfStream occurred,disconnecting.
private void doSomething(someProcessModel process){
CustomerModel customer = process.getCustomerModel();
customer.getFoos().stream()
.filter(foo -> foo.getCountryCode().equals(process.getCountryCode()))
.findFirst()
.ifPresent(foo -> {
if(foo.getSomeNumber() == null){
foo.setSomeNumber("1234567");
modelService.save(foo);
}
});
}
As seen in the code snippet above, I have a 'CustomerModel' that has an attribute 'Foos'. It's a one-to-many relationship. As you can see I have done some filtering and in the end, I want to update the value of 'someNumber' attribute of 'Foo' if it is null. I've confirmed that everything is working as the "someNumber" attribute's value is updated during the debugging. It doesn't save at all as I have done my checking in the HMC. I have also validated that the Interceptor doesn't have any condition that would throw an error. There is nothing being shown in the log either.
I am wondering is it a legal approach to do the "modelService.save()' inside the 'ifPresent()' method? What could be the possible issue here?
I have found the root cause now as I have face the same issue again.
Context to my original question
To give more context to my original question, the #doSomething method resides in a Hybris Business Process action class and I have ended the action prematurely while I am debugging it (by stopping the debugging) once the #doSomething method is ran.
Root cause
The mentioned problem happened when I was debugging the action class. I assumed that the ModelService#save will persist the current state of the business process once it has been ran. However, the Hybris OOTB business process will do a rollback if there is any error (and I believe it was caused by me stopping the debugging half-way).
SAP Commerce Documentation:
All actions are performed inside their own transaction. This means that changes made inside the action bean run method are rolled back in case of an error.
Solution
Let the action runs completely!
Good to know
Based on the SAP Documentation and this blog post, there will be times that we will need to bypass a business process rollback even though there is an exception being thrown and there are ways to achieve that. More info can be found in this SAP Commerce Documentation and the mentioned blog post.
However, in some circumstances it may be required to let a business exception reach the outside but also commit the transaction and deal with the exception outside. Therefore, it is possible to make the task engine not roll back the changes made during a task which failed.
You have to be cautious with a list in models as they are immutable, you have to set the whole new list. Also you called save only on a particular model, which changes its Jalo reference, that's why your list is not updated. Mutating stream and collecting it in the end will create new list that's why you can stream over the list directly from the model.
private void doSomething(someProcessModel process){
CustomerModel customer = process.getCustomerModel();
ArrayList<FooModel> foos = doSomethingOnFoos(customer.getFoos());
customer.setFoos(foos);
modelService.saveAll(foos, customer);
}
//compare the value you know exists with something that might be NULL as equals can handle that, but not the other way around
private ArrayList<FooModel> doSomethingOnFoos(ArrayList<FooModel> fooList) {
return fooList.stream()
.filter(Objects::nonNull)
.filter(foo -> process.getCountryCode().equals(foo.getCountryCode()))
.filter(foo -> Objects.isNull(foo.getSomeNumber()))
.map(foo -> foo.setSomeNumber(1234))
.collect(toList());
}
I've already searched via google and on stackoverflow, but could not find any similar problem to mine.
In my project I'm handling a ViewExpiredException properly and show a custom page to the user that the current session has timed out. This works great, but I want to do something BEFORE this message gets shown to the user. Actually I'm working with 2 different sessions here, one on the frontend side and one on the backend, so the idea is to NOT start a new backend session when the current one timed out.
Is there any possibility to fetch the ViewExpiredException while I'm inside the doFilter method, so I do not start a new backend session (simply because it is not needed)? Or is there any other way?
I already tried to fetch the current context via
FacesContext fc = FacesContext.getCurrentInstance();
But obviously the context is null, because the session timed out.
Inside the ExceptionHandlerWrapper I have access to the UnhandledExceptionQueuedEvents, but this does not help me here since I need this information earlier.
I hope I made my problem clear enough.
Thanks in advance for any help!
Regards
Sebastian
Generally ViewExpiredException is thrown when a POST request is fired while the session is timed out. So, this should do in the filter:
boolean post = "POST".equals(request.getMethod());
boolean timedout = request.getRequestedSessionId() != null && !request.isRequestedSessionIdValid();
if (post && timedout) {
// JSF will guaranteed throw ViewExpiredException when state saving is set to server.
}
But this does not cover all possible cases. ViewExpiredException can also occur when the session hasn't timed out. For example, when the client has passed an invalid javax.faces.ViewState parameter, or when the associated view has been pruned from the LRU map which can by default hold 15 views. This is however not detectable inside a servlet filter before FilterChain#doFilter() is called. You really need to be inside the JSF context. You could do the backend session creating job in a PhaseListener. E.g. in beforephase of apply request values phase, which is guaranteed to be invoked only when there's a vaild view.
By the way, the FacesContext is not null in the filter because the session has timed out, but because the FacesServlet, the one responsible for creating it, hasn't been invoked yet at that point. You know, filters run before servlets.
I am using valueUnbound method of HttpSessionBindingListener to release lock(an entry from the database), before session is about to expire:
#Override
public void valueUnbound(HttpSessionBindingEvent event) {
String user = (String) event.getSession().getAttribute("currentUsr");
removeLock(user);
}
When the lock is set, I am setting up the username as a session variable.
I need this "username" in my remove lock method. But the getAttribute is throwing an exception:
java.lang.IllegalStateException: getAttribute: Session already invalidated
I need help in getting the session variable?? or is there any other way to get the username?
No, since session has been invalidated.
Although, I figured out the solution, I am setting the attribute via servlet context in
valueBound method and getting it through the : event.getSession().getServletContext().getAttribute("cUser");
it works fine. Thank You EJP
I got your point EJP, you are right , I am making it complex, I can get it from event.getValue() . +1 to your answer, Thank You.
Although, I figured out the solution, I am setting the attribute via servlet context in valueBound method and getting it through the : event.getSession().getServletContext().getAttribute("cUser");
So.. You are storing session scoped data in the application scope. Do you realize that this way the data is shared among all visitors of the webapp? Visitor X would then see the attribute set by visitor Y which has visited the website at a later moment. It makes the problem only worse.
Anyway, as to the concrete problem, as the exception message is trying to tell you, the session has already been invalidated at that point. There are two ways to solve this:
Make currentUsr a property of the class which is implementing HttpSessionBindingListener, so that you don't need to grab it as a distinct session attribute.
Use a HttpSessionListener instead. The sessionDestroyed() method is called right before invalidation, so you should still have access to all attributes.
preface note: I'm just starting to learn Grails, so I'm sure there are many other problems and room for optimization.
I've got two domains, a parent (Collection) and child (Event), in a one-to-many mapping. I'm trying to code an integration test for the deletion of children. Prior to the code in question, I've successfully created a parent and three children. The point where I'm having problems is getting a single child in preparation to delete it. The first line of my sample code is only there because of my rudimentary attempt to troubleshoot.
// lines 95-100 of my EventIntegrationTests.groovy file
// delete a single event
assertEquals("2nd Event", event2.title) // passes
def foundEvent = Event.get(event2.id) // no apparent problems
assertEquals("2nd Event", foundEvent.title) // FAILS (line #98)
foundEvent.delete()
assertFalse Event.exists(foundEvent.id)
The error message I'm getting is:
Cannot get property 'title' on null object
java.lang.NullPointerException: Cannot get property 'title' on null object
at edu.learninggrails.EventIntegrationTests.testEventsDelete(EventIntegrationTests.groovy:98)
What should my next troubleshooting steps be? (Since the first assertEquals passes, event2 is clearly not null, so at this point I have no idea how to troubleshoot the failure of the second assertEquals.)
This is not evident from the code: did you persist event2 by calling save()? Get will try to retrieve it from the persistent storage (the in-memory database for example) and if the event wasn't saved, the retrieved instance will be null.
If you did save it, did the save go through OK? Calling event.save() will return false if there was something wrong while saving the item (like a validation error). Lastly, you might try calling event.save(flush:true) in case the Hibernate session doesn't handle this case as you might expect (I'm not entirely sure about this one, but it can't hurt to try).
Try to print or inspect the event2.id on line 97 and check if you actually have an id, if so check if you actually get an Event object on line 97.
I dont think you saved the parent and its children successfully. after you save, you should make sure that every object that was persisted has a non null id, in your test.
What you are seeing is you created the event2 with a title, but didnt save it. It passes the first assertion because you created it. When you do the get, null is returned because your save failed.
in general for DAO integration tests i do the following
Setup -- create all objects Ill use in the test.
Save -- assert that all ids on saved objects are NOT null.
Clear the hibernate session -- this is important because if you don't do it, objects can be in the session from the previous operations. In your real world scenario, you are probably going to start with a find, i.e. an empty session. In other words, you are not going to start with anything in the session. If you are you need to adjust this rule so that the session in the test, when you start the actual testing part, is the same as the session of the code in the wild
Load the objects on which you want to operate and do what you need to do.