Netbeans Bound Field not updating GUI - java

I have setup a Netbeans form with a text-field bound to a bean property. The binding is supposed to be two-way, but only works one-way. Updates to the field in the GUI update the bean, but if the bean is updated, the GUI does not update.
The Netbeans generated code looks like this for each property:
binding=org.jdesktop.beansbinding.Bindings.createAutoBinding(
org.jdesktop.beansbinding.AutoBinding.UpdateStrategy.READ_WRITE, crmmast1,
org.jdesktop.beansbinding.ELProperty.create("${fname}"), lname,
org.jdesktop.beansbinding.BeanProperty.create("text"));
bindingGroup.addBinding(binding);
My bean has property change support added:
private PropertyChangeSupport changeSupport = new
PropertyChangeSupport(this);;
public void addPropertyChangeListener (PropertyChangeListener listener) {
changeSupport.addPropertyChangeListener(listener);
}
public void removePropertyChangeListener(
PropertyChangeListener listener) {
changeSupport.removePropertyChangeListener(listener);
}
public void firePropertyChange (String propertyName,
Object old, Object newObj) {
changeSupport.firePropertyChange(propertyName, old, newObj);
}
Within the sett for the properties I have:
public void setFname(String newName) {
firePropertyChange("fname", fname, newName);
this.fname = newName;
}
When I update the underlying bean, the bean updates but the textfield does not (even though I have verified that a property change event is being fired.

Ran into the same problem. Really annoying. It took me a long time to realize something about the AutoBinding: it appears to listen to actions within the Property context established between the Source and the Target that you specify in the createAutoBinding call. This is why entering text in the JTextField updates to your bean property with no problem. It's on the same binding 'rail' so to speak.
What this means is that when you attempt to update your JavaBean via its setX() call directly from another source, like I was doing with a JFileChooser, the members of the autobinding don't see it, even though the firePropertyChange method is called.
doing this does not work:
myBean1.setFileLocation(fileChooser.getSelectedFile().getAbsolutePath());
So, instead of doing that call, what I instead did was make sure the Binding had a 'name' attached to it, which gets placed as the last parameter in the createAutoBinding() call. I did this in the Netbeans Matisse Property editor Bind popup Tool under the Advanced tab. In the example below, it is named "fileLocation".
binding = org.jdesktop.beansbinding.Bindings.createAutoBinding(
org.jdesktop.beansbinding.AutoBinding.UpdateStrategy.READ_WRITE,
myBean1,
org.jdesktop.beansbinding.ELProperty.create("${fileLocation}"),
jTextField12,
org.jdesktop.beansbinding.BeanProperty.create("text"),
"fileLocation");
bindingGroup.addBinding(binding);
The call that got me on the binding 'rail' so that the JTextField would update with my selected file looked like the following:
Binding fileBind = bindingGroup.getBinding("fileLocation");
Property fileProp = fileBind.getSourceProperty();
fileProp.setValue(myBean1, fileChooser.getSelectedFile().getAbsolutePath());
I had to pull this up with getBinding() and getSourceProperty() from the global binding group because Matisse locks out direct access to the original binding, and I am not supposed to edit it since the code is autogenerated. If you are hand editing your code, then you could always ensure that you have an available name to access the Property object directly.
In any case, the key to get an 'outside influencer' to work on the bean and the JTextField is to perform your changes on the Binding Property itself.

Recently I tried Swing GUI creation with netbeans and I was wondering about exactely the same issue (therefore found your post).
Your solution should work. There are only two things to keep in mind:
You will have to provide the correct prorperty name once you propagate bean changes (fname in your case should be ok)
The actual bean property has to be changed before changeSupport.firePropertyChange is being called. See: http://wiki.netbeans.org/BestPracticesWithJPAAndBeansBinding
Once these two things are obeyed, everthing should work. I also used JFileChooser to change a text field and there is no need to set the properties of the binding manually (as suggested by the other answer).

Related

Override ModelAttribute with Path Variable in Spring Framework

I'm developing API using Spring Framework and faced a problem that can be solved by simply adding a necessary logic to every place I have it, but I think that there might be an elegant solution to fix it.
I have the following method in my controller:
#GetMapping("/user/{userId}/permissions")
public List<PermissionDto> list(#PathVariable long userId,
#ModelAttribute #Valid PermissionCriteria criteria) {
return permissionService.list(criteria);
}
The thing is that in dto I have a field called userId. It's made not to have a lot of arguments going to the method of the service. But, I want this user id to be set exactly from path since I use the URL that specifies that we are adding permission exactly to specific user resource. It's doable by making addition line that uses setter in the criteria and sets the value of userId. However, now I should never forget to add this line every time I have a case like that. That's why I decided to move it to InitBinder:
#InitBinder(PERMISSIONS_CRITERIA_NAME)
public void permissionsCriteriaInitBinder(WebDataBinder binder) {
PermissionsCriteria criteria = (PermissionsCriteria) binder.getTarget();
Optional.ofNullable(requestHelper.getUserId())
.map(Long::parseLong)
.ifPresent(criteria::setUserId);
}
It works fine. The user ID is set from the path. However, If I specify request parameter and path variable at the same time, even though userId is set from the path in init binder, it's overridden afterwards before it goes to the controller method. So, this one doesn't solve all the issues.
What I want to find, is someplace where the logic can be put to apply to both init binder(I need it for validation) and controller method. Maybe there is a special type of hook or interceptor or at least something to implement to satisfy this conditions?

Execute function from model in viewcontroller

In my App (Fusion Web) exist a ViewObject from Oracle DB.
I created the java classes and build a specific method (makeUniqueSearchByDate(String)) to process the data.
This method appears in "Data controls" that I can drag to the "view" and use as any other function. When I try to use it in a "bean" (instead of dragging directly):
public void setDate(ActionEvent actionEvent) {
ApplicationModule appMod =
Configuration.createRootApplicationModule("com.svr.model.AppModule", "AppModuleLocal");
ViewModelosByDataImpl fo = (ViewModelosByDataImpl) appMod.findViewObject("ViewModelosByData1");
String dateV = "07-01-2013";
fo.makeUniqueSearchByDate(dateV);
}
This code has no effect on the table. Can anyone see why?
Btw, the program does not throw any exception. Just does not work. The table remains the same. But if I use the button, automatically generated by "drag and drop" the function runs normally. I know I should study ADF, but unfortunately I have no time.
i think after you have exposed the method written at VO as Client interface, you need to create a method binding in pageDef file of you page. after creating the method binding, you need to access the method in bean through binding layer something like this :
OperationBinding op=((DCBindingContainer)BindingContext.getCurrent().getCurrentBindingsEntry()).getOperationBinding("Method Binding");
op.execute();
i think the method used by you to call VO method from bean is not right.
i think one more thing you need to do in your bean after calling the VO method is that you need to do refresh the table / perform PPR programatically :
AdfFacesContext adfFacesContext = AdfFacesContext.getCurrentInstance();
adfFacesContext.addPartialTarget(component binding for your table component);
you can try setting autosubmit to true for command button which invokes action event, and set partial trigger for table to component id of the command button.
can you post VO method code as well ?
does the method get called and data gets committed / updated when you execute it through bean ? is it only a table refresh issue ? do you see changes to data if you manually refresh the page ?

how to refer to the property of bean used in BeanEditForm (tapestry5) in Java?

I've got in my .tml file something like this:
<t:beaneditform t:id="adForm" object="editableAd"
reorder="actiontype,shops,movies,streams,widgets" ....
My question is how to access (refer) actionType, which is an Enum (and in fact SELECT) in .java file? I just need to handle event when user changes the value of this select (dropdown), obviously before submitting the form itself.
If something like this would work for me...
#OnEvent(component = "adForm.actionType", value=EventConstants.VALUE_CHANGED)
public void actionTypeValueChanged(String value) {
log.info("value is: " + value);
}
To be updated with the changed value in a Select html component on the client side, have a tapestry select component in your template file with a t:zone attribute (i.e. in your case it could point to any dummy zone, this is only needed to be set correctly if you need to update a zone when a value is changed)
Also set the t:value attribute to your enum variable in your page\component java file, usually this variable will be annotated with tapestry's #Property.
Example:
<t:select t:id="myEnumVariable" t:zone="dummyZone" t:value="myEnumVariable"/>
myEnumVariable is used to refer to your class's variable AND to act as an ID (i.e. the actual string myEnumVariable is used as an id), this is not necessary, but it's more readable and maintainable that way)
public class MyClass{
#Property
private MyEnum myEnumVariable;
#OnEvent(component = "myEnumVariable", value=EventConstants.VALUE_CHANGED)
public void actionTypeValueChanged(**MyEnum** newValue) {
this.myEnumVariable = newValue; // <<<<<<
log.info("value is: " + myEnumVariable );
}
}
If you don't mind using the ChenilleKit framework for tapestry you could try using the
framework's OnEvent mixin.
You 'll find the example on the link I share but basically you add two attributes the select tag:
<t:select t:id="myselect" ... t:mixins="ck/OnEvent" t:event="change" />
then you add the event handler on your java class:
#OnEvent(component="myselect", value='change')
public void onChangeDoSomething(String value) {
hope that helps, by the way I think Muhammad's answer is equally correct (and doesn't requires the use of an extra framework).

Using Stripes, what is the best pattern for Show/Update/etc Action Beans?

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);
}

NetBeans Platform - how to refresh the property sheet view of a node?

I am using the PropertySheetView component to visualize and edit the properties of a node. This view should always reflect the most recent properties of the object; if there is a change to the object in another process, I want to somehow refresh the view and see the updated properties.
The best way I was able to do this is something like the following (making use of EventBus library to publish and subscribe to changes in objects):
public DomainObjectWrapperNode(DomainObject obj) {
super (Children.LEAF, Lookups.singleton(obj));
EventBus.subscribe(DomainObject.class, this);
}
public void onEvent(DomainObject event) {
// Do a check to determine if the updated object is the one wrapped by this node;
// if so fire a property sets change
firePropertySetsChange(null, this.getPropertySets());
}
This works, but my place in the scrollpane is lost when the sheet refreshes; it resets the view to the top of the list and I have to scroll back down to where I was before the refresh action.
So my question is, is there a better way to refresh the property sheet view of a node, specifically so my place in the property list is not lost upon refresh?
The solution of firePropertySetsChange comes from this thread.
Just to make a clarification about my old answer as an unregistered user: Calling createSheet(null) will raise a NullPointerException. Use setSheet(createSheet()) instead.
The solution is to fire a property change for each of the changed property of the updated object. So, in context of the snippet in the question this could be something like:
public void onEvent(DomainObject event) {
// Do a check to determine if the updated object is the one wrapped by this node;
// if so fire a property sets change
Set<Property> changes = new HashSet<Property>();
// Populate the set from property set of the node using the event
// (or add all properties to force updating all properties)
for (Property change : changes) {
firePropertyChange(change.getName(), null, change.getValue());
}
}
Note that property set should not be changed as that would mess with the property editors. Consequentially, the actual Property objects have to support changing of the domain object behind the property.
You could also set the node's property sheet to null, so the createSheet method is called again.

Categories

Resources