Win a copy of Cross-Platform Desktop Applications: Using Node, Electron, and NW.js this week in the JavaScript forum!
  • Post Reply Bookmark Topic Watch Topic
  • New Topic

Using getRowData method with an array index in a ListDataModel  RSS feed

 
Jay Tai
Ranch Hand
Posts: 222
Java MySQL Database Netbeans IDE
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I'm trying to create a folder based document management system where the user clicks a link from a list of folders (ListData<ProjectDocs>folderList) then gets a list of documents (ListDataModel<ProjectDocs>docList) pertaining to the selected folder. The folder list displays correctly using the following JPA method:




The user then chooses the desired folder from the below xhtml page:




The problem occurs in the getRowData method of the below controller beans:



The stack trace is:



So, I notice that the folderName STRING parameter is being returned as an Object from the xhtml. It cannot be cast s as a ProjectDoc type in the getRowData() method of the controller beans, which means I cannot use the ProjectDoc instance to return the folderName string that correctly populates the JPA parameter (folderName). Do I need to implement a converter class to return the #{docs[0]} as a String or is there another way to get the folderName String from the xhtml and populate this as the query parameter. Thanks in advance for any guidance!

 
Tim Holloway
Bartender
Posts: 18662
71
Android Eclipse IDE Linux
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
There seems to be something odd about your basic architecture. Aside from the fact that you're calling the backing bean a "Controller" :hunf:

You start off with what appears to be a JPA request to obtain database rows, but you don't appear to be returning the rows as ORM Entities, just a raw array of objects. Seems to defeat the purpose. Plus it's added maintenance expense.

This would be more appropriate:



And when the "selectFolderDocs" action method fired, The JSF framework would have set the folderList model object's cursor such that the following logic would correspond:



I added the cast, since I seem to recall that JSF can give compile problems otherwise.

As it stands, however, it appears something like you're displaying a raw object array but expecting a specific object type to be returned.
 
Jay Tai
Ranch Hand
Posts: 222
Java MySQL Database Netbeans IDE
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
OK thanks for pointing my continued misunderstanding of beans. I'd like to take that up after solving the concrete problem because I THINK i'm finally getting the backing bean 'theory' (crossing my fingers but not holding my breath).

So back to the concrete issue:

This would be more appropriate:

<h:commandLink action="#{projectDocBean.selectFolderDocs}"
value="#{docs.classification}" />



So this is the first thing I tried and it gives a "NumberformatExceptionForInputString" when trying to render the xhtml. I'm not sure why this is happening but I think it's because my JPA query selects separate fields from the entity class instead of selecting the entire ProjectDocs entitiy. IE:



Returning separate fields seems to turn the query string into an array. Maybe this is why the folder displays when I use array index #{doc[0]}. For sure I would like to use the way you described by simply calling the classification field from the list. Not having much luck figuring that out yet.

For the JPA/ORM I figure that I need to select separate entity fields because I want to return distinct folder names instead of a full document list with the related folder names next to each document. My underlying design might be wrong. It might be better to simply have a separate folders table and establish an entity relationship with the main document table. I will consider a better design, but if only for my own knowledge, I would like to figure out how to use the DISTINCT keyword in my ORM correctly.
 
Tim Holloway
Bartender
Posts: 18662
71
Android Eclipse IDE Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I knew what I meant when I started, then kind of lost track of myself.

Yes, JPA wants to return the ENTIRE entitity (subject to lazy-loading conditions) when you do a fetch. When you use an explicit SELECT (native OR jpql) in a query, what you get back is going to be an array of Objects.

If there's good reason to only want selected columns - like, say you only need 5 columns and the table has 150 columns*, you can define a results class for the query and JPA will instantiate rows of that class. I've done it using Hibernate JPA and it works quite well.

---

*Unfortunately, I've worked with some tables like this and really gotten steamed with Oracle and DB2 when they returned a generic "Bad data type for column" message or something similar instead of indicating which column(s) were being mis-applied. The open-source DBMS's tend to be more friendly that way.
 
Jay Tai
Ranch Hand
Posts: 222
Java MySQL Database Netbeans IDE
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Well I'm using Hibernate and MySQL (and not looking forward to the Oracle migration).

If there's good reason to only want selected columns - like, say you only need 5 columns and the table has 150 columns*..


Maybe I can clarify my reason for wanting selected columns with a brief example. Suppose my schema was structured like:

Next to each docName there's going to be the folderName. When requesting a list of folders I don't want to see a whole list of documents, JUST the distinct folder names. Not sure if that makes sense, but that's why I want to use DISTINCT in the JPQL

, .....you can define a results class for the query and JPA will instantiate rows of that class.I've done it using Hibernate JPA and it works quite well.


So this comment touches on the subject of models and controllers which I want to discuss before asking about the results class :)

Referring to a previous post:
http://www.coderanch.com/t/648144/JSF/java/JPA-query-parameters-JSF-render You said:
A JSF backing bean is always a Model if it contains any referenceable properties ('value=' targets) in it. The non-property methods (listeners and action methods) are not Controller logic.


Before attempting to write this class, I have a few questions:

1) Where does this class fit into the MVC architecture? Should it go into the same package as the backing bean? Is it a view model?
2) What is the class actually trying to achieve? Is it supposed to convert the string from an array object to a string?
3) Do you have any examples of such a class? Can I just utilize any of the existing model classes or backing beans by writing the appropriate conversion methods?

So the first question before attempting a results class is, could this class be part of the backing bean? My guess is it would reside in the JPA / Model package?

 
Tim Holloway
Bartender
Posts: 18662
71
Android Eclipse IDE Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Bear in mind that a JSF GUI Model object doesn't have to contain only items that are to be rendered. The View is at liberty to only reference items that it actually wants to display and/or update and ignore the rest. That''s true both of the primary GUI Model (Backing Bean) and for sub-Model obects such as DataModel row objects.

Since JSF GUI model objects are POJOS and ORM persistent data model objects are also POJOS, people can - and do - often double up, using ORM model objects as GUI models. In fact, so much so that many people don't even realize that there's a distinction.

So if you want to fetch an entire database row object and use it as a DataTable row model and ignore certain columns in that object on the GUI, that's perfectly legitimate. Or, if you want JPA to construct a custom object with only a selected few columns and use that object type as the GUI rowdata model, that, too is fine. OR, if you want to define a database View, make a JPA Entity model object of that and use it as a row data model, that, too is fine. I've done all of the above.

If you do construct a data view class that's to be populated by JPA - either mapped to an actual table View or to a query, that would be technically part of the ORM data model (Entity data) and only incidentally part of the GUI Model. So I put such things in my persistence class package, not the package where I defined backing beans and other JSF-only objects.

If you do any of those things, your question #2 becomes moot. Right now, what you are getting back is one of these:



But you're trying to treat it like it's something else (a ProjectDocs object). Hence the exception being thrown.
 
Jay Tai
Ranch Hand
Posts: 222
Java MySQL Database Netbeans IDE
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
OK so I need to convert the tuple into type ProjectDocs? I'm researching the following example:


Is the above the right direction to achieve the desired conversion? If it is, then the next thing I need to do is include the class reference in the ORM query method and here is where I'm really stuck:



 
Tim Holloway
Bartender
Posts: 18662
71
Android Eclipse IDE Linux
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Here's a real-world example. It's using the "?1" notation instead of the ":variable" name notation, but otherwise is similar.

The finder method in question locates all customers of a given winery:


That's in my DAO.

Now for the JSP data model code in the backing bean:



My particular architecture contains 3 tiers in the persistence layer: the bottom tier is the Entity model classes, the next one is the DAO tier (single-table access) and the next one is the data Services tier (handles multiple tables as a unit in a transaction). So in this example, the customerService findAllCustomer method simply bounces down into the DAO findCustomerService method.
 
Jay Tai
Ranch Hand
Posts: 222
Java MySQL Database Netbeans IDE
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thanks for this tremendously helpful example which i've been playing around with for the past couple of days, but I'm still getting the same numberFormatException for input String "classification". Not sure where I'm going wrong. So I modified your example as follows:

the ORM method:


The backing bean (A JSF Managed Bean. I tried also with a CDI bean which produced a NPE)



The JSF page:



The stack:



 
Tim Holloway
Bartender
Posts: 18662
71
Android Eclipse IDE Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
You are blowing up because your SELECT statement is attempting to retrieve selected columns rather than the entire entity. That causes JSF to return a list of Object[] instead of the entity type (ProjectDocs).
 
Jay Tai
Ranch Hand
Posts: 222
Java MySQL Database Netbeans IDE
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Sorry. I should have emphasized that the query returns a tulle, so I'm looking for a way around that. Would a custom conversion class be more relevant than defining a result class? I ask because I'd like to know the difference that defining a result class has made in compared to using my prior 'conventional' ORM method? Should I continue defining this class and add a custom converter? Thanks a lot!
 
Tim Holloway
Bartender
Posts: 18662
71
Android Eclipse IDE Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
The easy way is to just simply return the full row entity. In JPQL:



Although I suppose that that doesn't work well with SELECT DISTINCT.

Failing that, the cleanest alternative is to define either a database View+Entityclass or a resultType class. Like so:



I recommend that you obtain a of "Pro JPA2" by JKeith and Schincariol from aPress. Or whatever the current equivalent is. It's available in both dead-tree and eBook forms. I use it as my "go-to" guide for stuff like this.

 
Jay Tai
Ranch Hand
Posts: 222
Java MySQL Database Netbeans IDE
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Yes I forgot about that 'lil JPA bible'. So here's what I've done so far. I added a wrapper class for the result:





The Problem of displaying the folder list is now solved. Just need to display a document list from the selected folder list. Thanks for your help and hopefully I'm closer to solving the problem
 
Tim Holloway
Bartender
Posts: 18662
71
Android Eclipse IDE Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
One other thing. In the app I purloined that sample from, the Result class was defined as a stand-alone @Entity class. So I also have the mandatory no-element constructor, field accessors and appropriate equals() and hashCode() method implementations just like I would with a stand-alone table or view entity.

You might not get proper behavior if you don't do likewise.
 
Jay Tai
Ranch Hand
Posts: 222
Java MySQL Database Netbeans IDE
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I haven't noticed any strange behavior. I am however having problems getting a document list from the folder list. Using the same JSF page for the folder list:




Calls the method in the backbean:



Produces the following stack:


I see why a String cannot be cast to a ProjectDocs type. I've tried manually type casting it but that results in the same error. I don't think there's any way around to pass the Classfifcatin String (folderName) as a parameter from the folder list to display the document list based on the selected folder from the list. So I guess my final question is how can I pass the folder Name without running into the ClassCastException?
 
Tim Holloway
Bartender
Posts: 18662
71
Android Eclipse IDE Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Well, you did do a select into a "Classification" type object. You cannot expect to store a list of Classification's in a DataModel that's of type "ProjectDocs"!
 
Jay Tai
Ranch Hand
Posts: 222
Java MySQL Database Netbeans IDE
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
But the select I'm I'm doing is selecting FROM the ProjectDocs entity. The Classification is just the String criteria of the query?? :



The list I'm storing is of type ProjectDocs where I'm trying to grab the values from a type casted DataModel which is also of type ProjectDocs.


From my understanding, a DataModel is an abstracted collection that supports per row processing for their child components (implementations). A ListDataModel is an implementation of DataModel that wraps a List Java objects. Type casting a DataModel into a ListDataModel results in no compile time error, but produces a run time error. Is this because the type casting of DataModel into ListDataModel is fundamentally incorrect OR because the Classification wrapper class invalidates the FROM part of the query? Should the Classification wrapper class include a fully qualified implementation of ListDataModel that itself places the Classification string into a list of type ProjectDocs?
 
Tim Holloway
Bartender
Posts: 18662
71
Android Eclipse IDE Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
It matters not what you are selecting FROM. You could be selecting from multiple tables (JOIN query). The result object is what you select INTO.

The original DataModel class was untyped. In JSF2, it became a generic class. However, one of the perils of casting is that there's virtually no compile-time type safety for a cast operation. You don't find out that you're not working with the right sort of object until runtime - when you get slammed with a ClassCastException. Java generics are fairly weak in that respect.

Which is why you need to define a ListDataModel<Classification> to hold the returned data.
 
Jay Tai
Ranch Hand
Posts: 222
Java MySQL Database Netbeans IDE
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
OK I get that but I don't see how that will work in my case. I want to get a list of type ProjectDocs where Classification is a String which will then be used by a getRowData method to retrieve a consecutive list of documents that is also of ProjectTypes. If I define ListDataModel<Classification> wouldn't that conflict with ProjectDocs.class.getSimpleName()? Could a ListDataModel<Classification> then be used to retrieve a ListDataModel<ProjectDocs> folderedDocumentList?
 
Tim Holloway
Bartender
Posts: 18662
71
Android Eclipse IDE Linux
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
No, the ProjectDocs.class.simpleName() is just an abstract way that I have of referencing the FROM object, which is "ProjectDocs". The output is going to be put in a collection of objects of type Classification.

If you want the JSF GUI model type to be ProjectDocs, then you're going to have to create a List of ProjectDoc, then iterate through the list of Classification object, using each one to instantiate a ProjectDoc using the Classification object's property values to populate the corresponding ProjectDoc properties.

It's easy to simply make the DataModel be a list of Classification objects and use the list directly, considering that inherently there aren't going to be any values in a ProjectDoc that weren't in the returned Classification object anyway.

 
Jay Tai
Ranch Hand
Posts: 222
Java MySQL Database Netbeans IDE
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thanks for the clear explanation The presence of the Classification wrapper clouded my logic (which isn't hard to do). I want to take a step back to put into context what I'm trying to achieve. I want 2 lists (ie: folderList and docList). doclist gets a list of documents from folderList based on a selected folder. So, if folderList is of type Classification, then the DataModel must aso be of the same type and so should the docList. It's necessary and simpler to keep the list types consistent throughout the application if i want to avoid loop iterations needed to transfer data if i use lists of different types. Correct?

Before I tinker further with this, I would like to firm up my understanding of the underlying concept. Couldn't I just use the ProjectDocs entity class to begin with instead of making the Classification class? The Classification entity just seems redundant now that I know it can't simply be used as a convenience result wrapper without affecting the type casting of the rest of the application. ProjectDocs entity has the fields needed for the foderList and docList. If there's any reason I have to use Classification class, I would needto add extra fields to display the docList. So, if I can use ProjectDocs, the query in the ORM for folderList becomes:



The ProjectDocs entity:



 
Jay Tai
Ranch Hand
Posts: 222
Java MySQL Database Netbeans IDE
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
So basically I just used the ProjectDocs class instead of classification for the entire application and was successfully able to display the folder and select appropriate documents from that list. This was largely thanks to your explanation and my understanding of the real role of the wrapper class.
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!