aspose file tools*
The moose likes JSF and the fly likes Passing selected hyperlink value as where clause argument in query Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Java » JSF
Bookmark "Passing selected hyperlink value as where clause argument in query " Watch "Passing selected hyperlink value as where clause argument in query " New topic
Author

Passing selected hyperlink value as where clause argument in query

Jay Tai
Ranch Hand

Joined: Apr 25, 2012
Posts: 174

I have a mySql table of PROJECTS, which I am displaying as a list in the index.xhtml. The projectid column contains hyperlinks. When they're clicked I would like the specific projectid row selected to be passed as the query argument into another jsf file (ListProjects.xhtml) which displays all the project values referring to the projectid selected in the index.xhtml. The named query is:



index.xhtml


ListProjects.xhtml











I get the following stack trace. Would appreciate advice of how to correctly pass the hyperlink parameters. Please let me know if I should provide further information. Thanks in advance!
Tim Holloway
Saloon Keeper

Joined: Jun 25, 2001
Posts: 16228
    
  21

Unless you specifically want these links to be bookmarkable, I recommend that you do not attempt to parameterize them. It's not how JSF was designed to work.

The dataTable element works by defining a View template against a DataModel object. When you specify "value="some sort of List"", JSF constructs an anonymous DataModel and wraps it around the List. This is required because the display cursor mechanism requires additional platform-specific data to do its work and in order to allow using generic array and collection (POJO) objects without coding these items into them the wrapper provides a place to hold those additional items.

If, instead of referencing your List table model object directly, you explicitly create a ListDataModel in your backing bean and wrap it around your List, then reference that ListDataModel as your "value=" property on the dataTable, then you can use the h:commandButton and h:commandLink objects directly (without parameters) on rows in the table. The command action method can determine the row that was selected by using the ListDataModel's getRowData() or getRowIndex() methods and use them as part of the navigation process.

Note that when using dataTables, you MUST have an object in View scope or higher. Request scope will not retain the (explicit or implicit) DataModel object between requests, and the cursor information is therefore lost.

In truth, RequestScope is almost 100% useless in JSF. Which is why View scope was added.


Customer surveys are for companies who didn't pay proper attention to begin with.
Jay Tai
Ranch Hand

Joined: Apr 25, 2012
Posts: 174

OK thanks for one of the most informative explanations about dataTable I've read!! I need to simplify this explanation for my tiny mind to grasp. If I understood you correctly the steps that I need to take are:

1) Create a ListDataModel as a session bean using the View scope instead of the RequestScope.

How would the values of ListDataModel bean be different to the generic DataModel? After all it is referring to the same database objects.


2) Reference that ListDataModel as a dataTable value in the index.xhtml


3) Use getRowIndex method in commandLink tag to retrieve the values

I guess the commandLilnk action would need to map to the ListDataModel bean. Would I need the commandLink on the requesting page (index.xhtml) or the results page (ListProject.xhtml)? I guess both pages since I need to invoke actions on the requesting page to pass the 'clicked' value as a query argument and the results page to render the list based on the selected argument?




Tim Holloway
Saloon Keeper

Joined: Jun 25, 2001
Posts: 16228
    
  21

DataModel is an abstract base class. ListDataModel is an inheritance of that class that supports a POJO wrapped model of type java.util.List. There are other subclasses as well. For example, ArrayDataModel and JdbcDataModel.

You don't normally instantiate a table DataModel as an independent bean. It's usually a sub-model of some other Model bean, exposed as a read-only property of that containing bean.

You don't "pass" the row element on your View definition when using the DataModel. That's because the required information is already known server-side when your commandLink action method fires. All the action method needs to do is interrogate the DataModel object and the DataModel will return the row submodel of that object automatically.

In short form:


And



This makes the item name/description serve as a link to the detail view. In the detail view backing bean, the "data" property holds the specific record details, so the EL references in the detail view would be in the form "#{detailBean.data.description}".
Jay Tai
Ranch Hand

Joined: Apr 25, 2012
Posts: 174

Thank you. I'm now trying to apply the DataModel and ListDataModel to the context of my app and I'll come back when I've figured out your suggestions. I can see showDetails exposes the getRowData method from DataModel
Tim Holloway
Saloon Keeper

Joined: Jun 25, 2001
Posts: 16228
    
  21

This may help:

http://www.coderanch.com/t/624834/JSF/java/Howto-create-java-faces-model#2856975
Jay Tai
Ranch Hand

Joined: Apr 25, 2012
Posts: 174

It certainly helps to understand the DataModel concept but I'm still not following exactly what you did with the showDetails method in your example. The concept behind showDetails method seems clear. It's using the DataTable getRowData method to obtain the row data from the TableModel getter method (getTableModel). But what is MyDataRow? Is it a seperate class or interface or just an identifier?

I ask this because I imported the required libraries (javax.faces..DataModel and ListDataModel) in the showDetails class but I get a 'cannot find symbol' error for MyDataRow. Do I need to declare MyDataRow as a List object? I'm also getting errors for the getRowData method even though I've imported the required libraries.

I'm now wondering about the class around the showDetails method and what details this class should contain.
Tim Holloway
Saloon Keeper

Joined: Jun 25, 2001
Posts: 16228
    
  21

I (among others) use "My" as a prefix to indicate that the class in question doesn't have a fixed name, it's whatever class you like. Including classes that you define yourself.

So in your particular case, you'd substitute your class name "Projects" for MyDataRow, since Projects is the name of the ORM entity that presents one row of data in your dataTable.
Jay Tai
Ranch Hand

Joined: Apr 25, 2012
Posts: 174

If I understand correctly the TableModel is an instance of DataModel and GetRowData is a method from DataModel, so I'm tryingto create a SHowModel class which looks like:



I'm stuck with the MyDetails line and the injected Detail bean? Does MyDetails call a DAO class which contains a findByPrimaryKey query using the Entity Manager? Is the detail bean a managed bean which sets the properties of the Project List?


Jay Tai
Ranch Hand

Joined: Apr 25, 2012
Posts: 174

Well I've been researching this further in the past few weeks and came up with the following code. I understand the DataModel concept much better but I'm still going wrong somewhere since the following produces a NullPointerException.


index.xhtml





Should I be using the TablModel in the ObjectModel class as the value in my dataTable tag on the jsf page instead? When I replace #{mainController.allProjects} with #{objectModel.tableModel} the index.xhtml just produces a blank screen. This tells me that the TableModel is null so could this be the cause of the NPE?
Tim Holloway
Saloon Keeper

Joined: Jun 25, 2001
Posts: 16228
    
  21

I'm going to fire off some random shots here, some of which may not apply. Because I can see several things that set off alarms, even without attempting to actually understand what you are trying to do.

First off, no backing bean is a Controller. In JSF, the Controllers are pre-supplied as part of JSF itself. Backing beans are Models. Action methods should not be confused with Controller logic. All Controllers do is keep Model and View in sync and don't do business functions the way Action methods do. And action methods shouldn't be attempting to do Controller work, they should update the Model and let the real Controllers handle the rest.

Secondly, Request Scope is almost 100% useless in JSF. In the case of SelectItem and DataModel objects, you can remove the word "almost", because the original models are destroyed and re-created minus critical context on the next request.

Thirdly, while I don't think you're actually attempting to use an EJB as a JSF backing bean (the location of your annotation perplexes me), EJBs do not function well in the role of backing bean due to the relative inflexibility of Managed Bean instantiation.

Fourth, an action= attribute is supposed to be a reference to an action method, not an actual method call. The call is done by JSF, not by the View (which should be data, not code). So lose the "()".

You seem to be attempting to use a DataModel as a wrapper for detail data. It's supposed to wrap the rows of a collection.
Jay Tai
Ranch Hand

Joined: Apr 25, 2012
Posts: 174

This is very useful and shows me the gaps in my understanding of JSF fundamentals. Before I go through your comments and modify my code, I should say something about what I'm trying to do. This is just a test application where I want to generate a list of project IDs. Clicking each ID fires the <CommandLink> which should go to a bean that takes the ID parameter and returns an output page of the project details based on the selected ID. Please let me know if the application 'logic' doesn't make sense. I will now go through your comments and modify my code.
Tim Holloway
Saloon Keeper

Joined: Jun 25, 2001
Posts: 16228
    
  21

I think you need to study up on the concept of Inversion of Control. IoC is one of the core architectural features of JSF, as well as certain other frameworks (such as Spring).

Traditional programming has relied on active programming, where if component A wants something from component B, it goes out and gets it from component B. IoC flips that around. The framework itself pushes Component B onto Component A. That relieves Component A from the chore of having to locate Component B and to a large degree, from having to know what goes on in Component B. I call this the "TinkerToy" approach, since basically you have a bunch of parts that you can stick together. And one advantage of that approach is that it makes easier to swap parts in and out. For example, for testing, I may have a simulated emailer module replace the production's live emailer and I don't have to make code changes.

In the (very common) use case that you are describing, you don't have to export the database key of the item you want to home in on at all using JSF architecture.

The DataModel is, as I mentioned, a wrapper for tabular data display. It allows you to use generic (POJO) row data, but decorates it with contextual information that allows JSF to know what row you selected when you click on a commandLink or commandButton (or an AJAX control) that's in a row of the displayed table. The action method (or AJAX listener) that is then fired can query that DataModel (via getRowData or getRowIndex) to find the model row, and since usually the model row contains a key column(s), that's all that's needed to bring up details for editing.

The IoC comes in when it's time to edit details. By injecting a detail editing (child) Managed Bean into the table display (parent) Managed Bean, you can then have your parent bean set up the child for editing. Here's a typical scenario:


Typically, my detail editor bean will have a property named "data" or something original like that, which holds the actual ORM model object corresponding to the detail record, so that the editor form will contain references like this:


The "setupEdit" method does the actual fetch of that record from the database and stores it in the "data" property.
Jay Tai
Ranch Hand

Joined: Apr 25, 2012
Posts: 174

I think you need to study up on the concept of Inversion of Control


Do you recommend any specific books or material that deals with IOC? I'm now reading Core Java Serves Faces (Geary), which gives a good grounding on backing beans.

The IoC comes in when it's time to edit details


For the particular use case I mention here I do not need to edit. I only want to dsiplay values based on using the projectid as the WHERE clause argument. So, does IOC still apply if I want to simply display the resulting data using the DataModel as wrapper (even though I'm not actually editing any data in my user case)?
Tim Holloway
Saloon Keeper

Joined: Jun 25, 2001
Posts: 16228
    
  21

The difference between viewing details and editing them is merely the difference between using input/output form controls and output-only form controls. The backing logic is essentially the same, allowing for the fact that you don't need any save, update or delete action methods. IoC is a fundamental characteristic of JSF, so it really doesn't matter what you are doing - chances are that you'll be able to do it better using IoC techniques.

I cut my IoC teeth on a now-defunct Apache project. I am horribly uninformed on what good texts there are on current-day Java technologies. Probably you could find some good stuff on IoC in Spring documentation, though. Spring is all about IoC. Plus as a bonus, it works very well with JSF. My most important web projects are all JSF/Spring/Hibernate-JPA ones, with Spring providing most of the persistence logic.
Jay Tai
Ranch Hand

Joined: Apr 25, 2012
Posts: 174

Well I'd like to avoid Spring or Hibernate and learn 'crude' JSF to begin with before moving onto other frameworks. Or would you suggest learning and integrating Spring from the outset?
Tim Holloway
Saloon Keeper

Joined: Jun 25, 2001
Posts: 16228
    
  21

You probably wouldn't want to integrate Spring into a JSF app if you're just learning JSF.

But Spring is a useful item to have on one's résumé. So it's worth learning in its own right. Especially since you can learn how to use Inversion of Control in ordinary non-web apps using Spring, which means that you don't have to also know a lot about the web environment and you won't have to waste a lot of time building and deploying WARs and restarting webservers.
Jay Tai
Ranch Hand

Joined: Apr 25, 2012
Posts: 174

Sorry for the delayed reply but at last I solved this about a month ago and it needed a thorough read up on JSF, JPA and IoC. I do have more issues but the whole datamodel concept and the way JSF treats objects makes a lot more sense. Thank you!!
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: Passing selected hyperlink value as where clause argument in query