Let's say we have a domain entity defined this way:
interface MyNode {
MyNode getParent();
void setParent(MyNode node);
List<MyNode> GetChildren();
void AddChild(MyNode node);
void RemoveChild(MyNode node);
String getText();
void setText(String text);
}
I'm trying to implement a GWT web-app to work with these entities. I'm using request factory and editors framework. And I'm having some problems for sure :-)
Since the request factory definitions are trivial, I won't post them here. I'd only say that all the stuff related with children is a set of InstanceRequests.
So, the problem #1
Let's say we want to have a navigator for the whole tree. The idea is, every time we only see one node and we can either navigate to its parent or to one of its children. We'd like this navigator to use editors framework, so we build editors like MyNodeEditor and ChildrenListEditor.
As far as I know, editors only directly applicable to bean-styled entities. So, as long as working with MyNode text property is fine, working with children property (ChildrenListEditor) requires instance request.
My solution is, make MyNodeEditor to be a ValueAwareEditor and when it gets its value set, it initiates an InstanceRequest to get the list of child nodes. That list is then bound to ChildrenListEditor.
Are there any easier solutions? I believe it's quite a basic scenario.
Problem #2
We now decide to make our MyNodeEditor capable of editing. Bean-style properties are fine again, but what about children? Using the code mentioned in problem #1:
#Override public void setValue(MyNodeProxy value) {
...
requestFactory.myNodeRequest().getChildNodes().using(value).fire(new Receiver<List<MyNodeProxy>>() {
#Override public void onSuccess(List<MyNodeProxy> response) {
childrenDriver.display(response);
}
});
...
}
causes "Caused by: java.lang.IllegalArgumentException: Attempting to edit an EntityProxy previously edited by another RequestContext" because I'm having 2 different requests for the same entity here. I don't have access to RequestContext I've constructed at MyNodeEditor, so I'm constructing the new one and it fails. What's the right approach?
It'd be easier if you had a List<MyNodeProxy> getChildren() property on MyNodeProxy to access the children, rather than firing a distinct request.
You can access the RequestContext you passed to the RequestFactoryEditorDriver by implementing HasRequestContext on your editor. But in that case it won't help you, as firing it (from within your editor) would freeze it and thus make it unusable for anything else (such as saving the node after flushing the editor driver). If you cannot add a getChidren to your MyNodeProxy, then I'd suggest getting the children's list before you edit the node in the editor driver (alternatively, you could use a request based on the node's ID, rather than passing the node instance as an argument, or as a using() value, which is what's causing the error).
Related
There are countless questions here, how to solve the "could not initialize proxy" problem via eager fetching, keeping the transaction open, opening another one, OpenEntityManagerInViewFilter, and whatever.
But is it possible to simply tell Hibernate to ignore the problem and pretend the collection is empty? In my case, not fetching it before simply means that I don't care.
This is actually an XY problem with the following Y:
I'm having classes like
class Detail {
#ManyToOne(optional=false) Master master;
...
}
class Master {
#OneToMany(mappedBy="master") List<Detail> details;
...
}
and want to serve two kinds of requests: One returning a single master with all its details and another one returning a list of masters without details. The result gets converted to JSON by Gson.
I've tried session.clear and session.evict(master), but they don't touch the proxy used in place of details. What worked was
master.setDetails(nullOrSomeCollection)
which feels rather hacky. I'd prefer the "ignorance" as it'd be applicable generally without knowing what parts of what are proxied.
Writing a Gson TypeAdapter ignoring instances of AbstractPersistentCollection with initialized=false could be a way, but this would depend on org.hibernate.collection.internal, which is surely no good thing. Catching the exception in the TypeAdapter doesn't sound much better.
Update after some answers
My goal is not to "get the data loaded instead of the exception", but "how to get null instead of the exception"
I
Dragan raises a valid point that forgetting to fetch and returning a wrong data would be much worse than an exception. But there's an easy way around it:
do this for collections only
never use null for them
return null rather than an empty collection as an indication of unfetched data
This way, the result can never be wrongly interpreted. Should I ever forget to fetch something, the response will contain null which is invalid.
You could utilize Hibernate.isInitialized, which is part of the Hibernate public API.
So, in the TypeAdapter you can add something like this:
if ((value instanceof Collection) && !Hibernate.isInitialized(value)) {
result = new ArrayList();
}
However, in my modest opinion your approach in general is not the way to go.
"In my case, not fetching it before simply means that I don't care."
Or it means you forgot to fetch it and now you are returning wrong data (worse than getting the exception; the consumer of the service thinks the collection is empty, but it is not).
I would not like to propose "better" solutions (it is not topic of the question and each approach has its own advantages), but the way that I solve issues like these in most use cases (and it is one of the ways commonly adopted) is using DTOs: Simply define a DTO that represents the response of the service, fill it in the transactional context (no LazyInitializationExceptions there) and give it to the framework that will transform it to the service response (json, xml, etc).
What you can try is a solution like the following.
Creating an interface named LazyLoader
#FunctionalInterface // Java 8
public interface LazyLoader<T> {
void load(T t);
}
And in your Service
public class Service {
List<Master> getWithDetails(LazyLoader<Master> loader) {
// Code to get masterList from session
for(Master master:masterList) {
loader.load(master);
}
}
}
And call this service like below
Service.getWithDetails(new LazyLoader<Master>() {
public void load(Master master) {
for(Detail detail:master.getDetails()) {
detail.getId(); // This will load detail
}
}
});
And in Java 8 you can use Lambda as it is a Single Abstract Method (SAM).
Service.getWithDetails((master) -> {
for(Detail detail:master.getDetails()) {
detail.getId(); // This will load detail
}
});
You can use the solution above with session.clear and session.evict(master)
I have raised a similar question in the past (why dependent collection isn't evicted when parent entity is), and it has resulted an answer which you could try for your case.
The solution for this is to use queries instead of associations (one-to-many or many-to-many). Even one of the original authors of Hibernate said that Collections are a feature and not an end-goal.
In your case you can get better flexibility of removing the collections mapping and simply fetch the associated relations when you need them in your data access layer.
You could create a Java proxy for every entity, so that every method is surrounded by a try/catch block that returns null when a LazyInitializationException is catched.
For this to work, all your entities would need to implement an interface and you'd need to reference this interface (instead of the entity class) all throughout your program.
If you can't (or just don't want) to use interfaces, then you could try to build a dynamic proxy with javassist or cglib, or even manually, as explained in this article.
If you go by common Java proxies, here's a sketch:
public static <T> T ignoringLazyInitialization(
final Object entity,
final Class<T> entityInterface) {
return (T) Proxy.newProxyInstance(
entityInterface.getClassLoader(),
new Class[] { entityInterface },
new InvocationHandler() {
#Override
public Object invoke(
Object proxy,
Method method,
Object[] args)
throws Throwable {
try {
return method.invoke(entity, args);
} catch (InvocationTargetException e) {
Throwable cause = e.getTargetException();
if (cause instanceof LazyInitializationException) {
return null;
}
throw cause;
}
}
});
}
So, if you have an entity A as follows:
public interface A {
// getters & setters and other methods DEFINITIONS
}
with its implementation:
public class AImpl implements A {
// getters & setters and other methods IMPLEMENTATIONS
}
Then, assuming you have a reference to the entity class (as returned by Hibernate), you could create a proxy as follows:
AImpl entityAImpl = ...; // some query, load, etc
A entityA = ignoringLazyInitialization(entityAImpl, A.class);
NOTE 1: You'd need to proxy collections returned by Hibernate as well (left as an excersice to the reader) ;)
NOTE 2: Ideally, you should do all this proxying stuff in a DAO or in some type of facade, so that everything is transparent to the user of the entities
NOTE 3: This is by no means optimal, since it creates a stacktrace for every access to an non-initialized field
NOTE 4: This works, but adds complexity; consider if it's really necessary.
I have a tree viewer in my view, which listens to EMF models from the standard Ecore editor and does further things with it. I have already registered a selection listener, which checks whether the selected elements are the types the tree viewer needs as input. So the problem is that if there any changes in the model (e.g. adding a new element or new information to an existing element etc.) the tree viewer shows the changed model only if the user changes the selection, i.e. clicks to any model element etc.
But what I need to do is, that the tree viewer gets directly notified if the underlying model changes and shows the new model element too without being have to click on the model to listen it.
I have found the following eclipse corner article ( https://www.eclipse.org/articles/Article-TreeViewer/TreeViewerArticle.htm#inputChanged ) and from "Responding th change" it seems that the inputChanged() and refresh() methods might be the solution I am looking for, isn't it?
Still I was wondering if there is maybe an easier way to do this without being have to change the model code, but only by making changes in the UI code? Thanks!
You can call the TreeViewer refresh() method to get it to refresh the whole tree from the model, or refresh(Object) to refresh the tree starting at the given model object.
If the tree structure has not changed you can call update(Object) to just update the display of a single object.
There are also add and remove methods for when you add and remove objects from the model tree.
Some of the methods also have Object [] variants so you can modify several objects at once.
Update:
Your model should support generating a model changed event which the content provider can listen to. You would set up this listener in the content provider inputChanged method and remove it in the dispose method. When model change events are received use the various TreeViewer methods to update the tree.
An example of how all this is used are the Eclipse views which show the files in the workspace (such as the Navigator view). The content provider for these uses the workspace resource change listener (IResourceChangeListener) to be notified of changes to the workspace and using the information in the event calls the methods I listed above to update the tree.
Update 2:
An example of using IResourceChangeListener in a content provider, extracted from org.eclipse.ui.views.tasklist.TaskListContentProvider
class TaskListContentProvider
implements IStructuredContentProvider, IResourceChangeListener
{
private TableViewer viewer;
private IResource input;
... other methods ....
public void dispose() {
if (input != null) {
input.getWorkspace().removeResourceChangeListener(this);
input = null;
}
}
public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
if (input != null) {
input.getWorkspace().removeResourceChangeListener(this);
}
input = (IResource) newInput;
if (input != null) {
input.getWorkspace().addResourceChangeListener(this, IResourceChangeEvent.POST_CHANGE);
}
viewer = (TableViewer) viewer;
}
public void resourceChanged(IResourceChangeEvent event) {
... use resource change event to update viewer
}
}
By default Grails renders List in XML with a <list> element tag at its root. Likewise it renders Map with <map>. I would like to control the name of the root element.
If I'm returning an ArrayList of User, then I'd like to see:
<users>
<user>...</user>
<user>...</user>
</users>
How can I achieve the above? Here are the Requirements:
Easy to apply this serialization for 50+ domain classes
Abstracted from developers so no explicit coding is required during rendering domain objects (i.e., when render() or respond() is invoked, an ArrayList is still passed in, no explicit casting/converting like as MyNewType)
Able to handle the edge case of an empty list (should return <users/>)
Nice-to-haves:
If this formula can be applied to Map as well, great :)
I have been semi-successful in achieving the goals above, except I don't know how to account for the empty list case. I implemented my own ObjectMarshaller which renders all objects of type List. So long as the list contains one element, I can check the element's type and determine what the plural tag name should be (User => users). But if the list is empty, and since Java generics are by erasure (unless that's different in Groovy?) then I have no way to properly name an empty list other than defaulting to something like <list/>, which is not acceptable.
Some resources that I've been through:
http://www.cacoethes.co.uk/blog/groovyandgrails/dry-json-and-xml-with-grails
http://grails.1312388.n4.nabble.com/Custom-XML-Marshaller-change-the-root-element-name-td4649949.html
http://jwicz.wordpress.com/2011/07/11/grails-custom-xml-marshaller/
http://mrhaki.blogspot.com/2013/11/grails-goodness-register-custom.html
http://manbuildswebsite.com/2010/02/15/rendering-json-in-grails-part-3-customise-your-json-with-object-marshallers/
A way to achieve this is to write a subclass for the CollectionMarshaller class and register it in our Grails application. We can for example register a custom implementation in BootStrap.groovy with the following code:
import org.codehaus.groovy.grails.web.converters.marshaller.xml.CollectionMarshaller
import grails.converters.XML
class BootStrap {
def init = { servletContext ->
// Register custom collection marshaller for List with User instances.
// The root element name is set to users.
XML.registerObjectMarshaller(new CollectionMarshaller() {
#Override
public boolean supports(Object object) {
object instanceof List<User>
}
#Override
String getElementName(final Object o) {
'users'
}
})
}
}
To make this work for more domain classes we might get a reference to all domain classes in BootStrap.groovy and loop through them to configure custom CollectionMarshaller instances.
For maps you can extend MapMarshaller
Also described in http://mrhaki.blogspot.com/2014/02/grails-goodness-customize-root-element.html
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);
}
HI guys,
I wanted to add an AJAX Event to my Homepage, but it doesn't work! I figured out, that if I delete the onComponentTag function it works well. I have no clue why this happend, maybe you can help me!
Thats my Code:
final TextField<String> searchInput = new TextField<String>("searchInput", model) {
#Override
protected void onComponentTag(final ComponentTag tag) {
super.onComponentTag(tag);
tag.put("id", this.getId());
if (params.getString("search") != null) {
tag.put("value", params.getString("search"));
}
}
};
searchInput.add(new AjaxFormComponentUpdatingBehavior("onfocus") {
#Override
protected void onUpdate(final AjaxRequestTarget target) {
System.out.print("never saw that message :(");
searchInput.setDefaultModelObject("");
target.addComponent(searchInput);
}
});
Thx a lot for helping me!
CU
Firstly, you don't need to be overriding onComponentTag() at all. As seanizer states, if your really need to specify a markup ID yourself, use setMarkupId(id). You should understand why it is recommended that Wicket manages component IDs.
Secondly, the value attribute that you are adding is unnecessary - Wicket adds this automatically for this component. The value assigned is the value of the component's model object. See the source for TextField.onComponentTag().
Thirdly, again as seanizer states, components that are to be updated by ajax need to output their markup IDs - Wicket's ajax implementation uses the ID as the selector for the element. Additionally, all Wicket ajax behaviours that extend AbstractDefaultAjaxBehavior automatically set outputMarkupId(true) on the component they are bound to (see the source for AbstractDefaultAjaxBehavior.onBind()). This includes AjaxFormComponentUpdatingBehavior.
So:
String id = "searchInput";
final TextField<String> searchInput = new TextField<String>(id, model);
searchInput.setMarkupId(id);
searchInput.add(new AjaxFormComponentUpdatingBehavior("onfocus") {
#Override
protected void onUpdate(final AjaxRequestTarget target) {
System.out.print("never saw that message :(");
searchInput.setDefaultModelObject("");
target.setOutputMarkupId(true);
target.addComponent(searchInput);
}
});
Finally, I'd question what you're actually trying to achieve with this behaviour. I don't see any reason to round-trip this event to the server. Surely some client-side JS is more appropriate?
tag.put("id", this.getId());
is not the way to do it in wicket.
instead, use
component.setOutputMarkupId(true)
(either in your component constructor or in your behavior's bind() method) to make wicket write the id, and if you absolutely need to control what the id is (which is almost never the case) you can do
component.setMarkupId("myId")
also, you probably shouldn't assign the tag value yourself, use a model (model handling is extremely smart in wicket, read more about models). There are valid uses for onComponentTag, but they are way beyond what you are doing. Let wicket do what wicket does best and everything will be fine.
EDIT:
OK, some more clarification
have a look at the source code of AjaxFormComponentUpdatingBehavior, especially the part where the javascript event handler is generated.
protected final CharSequence getEventHandler()
{
return generateCallbackScript(
new AppendingStringBuffer("wicketAjaxPost('")
.append(getCallbackUrl(false)).append(
"', wicketSerialize(Wicket.$('"
+ getComponent().getMarkupId() + "'))"));
}
as you can see, wicket uses getMarkupId() to determine the actual id. The id you set using tag.put(id) is totally unknown to wicket and hence the behavior cannot work.
The standard thing to do is setOutputMarkupId(true). This is the only proper way to tell wicket to render the id (other than setOutputMarkupPlaceholder(true), which internally calls the former method). That way you make sure that the id wicket writes is the id wicket knows about. If this doesn't render the id, you are probably breaking some default behavior by overwriting onComponentTag.
Have a look at the source code of Component, especially at onComponentTag(), the method you are overriding:
protected void onComponentTag(final ComponentTag tag) {
// if(setOutputMarkupId(true) was set)
if (getFlag(FLAG_OUTPUT_MARKUP_ID)) {
// set id attribute
tag.put(MARKUP_ID_ATTR_NAME, getMarkupId());
}
}
[The comments are mine. BTW, this is the source of an ancient version, but I didn't find any current source online, and the functionality hasn't changed.]
Now if, as in your case, you want to set the component id manually, you must use
component.setMarkupId("myId")
and of course
setOutputMarkupId(true)
as well. If that doesn't work, go to the wicket JIRA site and file a bug. But I doubt it, this is standard functionality that works for thousands of users.