• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Liutauras Vilda
  • Jeanne Boyarsky
  • Devaka Cooray
  • Paul Clapham
Sheriffs:
  • Tim Cooke
  • Knute Snortum
  • Bear Bibeault
Saloon Keepers:
  • Ron McLeod
  • Tim Moores
  • Stephan van Hulst
  • Piet Souris
  • Ganesh Patekar
Bartenders:
  • Frits Walraven
  • Carey Brown
  • Tim Holloway

How to update in JSF/JPA?

 
Greenhorn
Posts: 3
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi to everyone, I'm new to use JSF and I'm trying to develop a simple CRUD application. I've already implemented the Create, Read and Delete operation, but I'm having problem with the Update operation.
When I'm trying to update I've this error:



index.xhtml


Entity class


Bean class


ManagedBean


When I debugged the application, I noticed that the variable b in the method is null, but I don't understand the reason. So is this the right way to update a record in DB? Or there are better method? Thanks!
 
Bartender
Posts: 20842
125
Android Eclipse IDE Tomcat Server Redhat Java Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Welcome to the Ranch, Simone!

JSF isn't intended to have logic in its view definitions. It's a Model/View/Controller architecture where the backing beans are the Models*, the Views are defined by View Templates (xhtml) and the Controllers were already written for you (you don't code Controllers in JSF).

When you define an action for JSF View form, you're not coding logic, you're providing a reference to the action method in the indicated backing bean. That, is, you shouldn't code:


Instead, code:


Now for the "*" note on Models. Technically, MVC is all Model, View, and Controller code, and all day long, all the Controllers do is take updates to the Models and post them to the Views and take changes to the Views and post them to the Models. But that's pretty useless in real life, so somewhere you need to attach some business and/or persistence logic. And in JSF, that's done with action methods.

A JSF action method takes no arguments, and returns a String value. The return value is a navigation directive telling JSF which View to display after the action is executed. If you return null, the same View is used.

So how does the action method know what data to work on? Well, since it's embedded in a Model, the easiest data for it to locate is obviously the data (properties) in that Model. Which is why action methods don't need arguments.

OK, but you're displaying a table full of rows of data. How does JSF know which row to work with?

It's actually quite simple. A JSF dataTable's value references a JSF DataModel object. If your value= attribute references a raw array or Collection, then JSF will construct an anonymous DataModel. Which is actually pretty useless unless you only want to display rows and not take action on them.

But if instead you construct a DataModel and wrap it around your array or Collection, then you can make that DataModel object be a read-only property (has "get", but no "set" method). Use this property instead of the raw array/Collection as your dataTable value= attribute, and now the action method has something to work with.

When the action method fires, it can use either the DataModel object's getRowData() method to get direct access to the data object for the row whose commandButton/commandLink or AJAX control was clicked (or fired). Or, use the DataModel getRowIndex() to get its array/list index.

The DataModel is a wrapper, so you only need to create it the first time something calls its "get" method. The data it wraps can change, but unless you replace the actual array or Collection and not merely alter its contents, the DataModel doesn't need to be altered. If you do need to replace the underlying data set, use the DataModel setWrappedData function to wrap the new data set.

The DataModel adds JSF capabilities to the underlying data so that you can use POJO data such as what JPA returns. It's a straightforward implementation of a decorator pattern, similar to the JSF SelectItem object class.

The DataModel actually holds cursor information between page requests, so you cannot use it in a Request-scope backing bean (request scope is almost totally useless in JSF anyway). You need View, Session or some higher scope.

And finally, actionListeners are almost never needed in modern JSF. Use action methods instead.
 
Simone Sabato
Greenhorn
Posts: 3
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi Tim, thanks for your answer but I don't understand completely which changes I should make. I tried to edit



in



as you suggested to me, but now I have "Method not found" error. So Can you please show to me what I have to edit in my code?

Thanks!
 
Tim Holloway
Bartender
Posts: 20842
125
Android Eclipse IDE Tomcat Server Redhat Java Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Your sample bean class didn't even include a "removeBook" method.

To work properly, you have to define a method in your bookBean that looks like this:
 
Simone Sabato
Greenhorn
Posts: 3
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
In the first post I didn't write the remove method in the BookBean class, as it works.

This is the entire BookBean class



and this is the entire Bean class:


In the code I wrote, I haven't any problem with the create, read and delete operation while the update operation doesn't work. So can you please me show what I have to modify in the Bean class or BookBean class to work the update operation? Thanks!
 
Tim Holloway
Bartender
Posts: 20842
125
Android Eclipse IDE Tomcat Server Redhat Java Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
In JPA, when you merge a detached object, it doesn't update the object you passed to merge. Instead, it creates an entirely new object and returns that from the merge method. At that point, the original object should be discarded, since it's no longer in sync.
 
It is sorta covered in the JavaRanch Style Guide.
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!