• 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
  • Jeanne Boyarsky
  • Bear Bibeault
  • Knute Snortum
  • Liutauras Vilda
Sheriffs:
  • Tim Cooke
  • Devaka Cooray
  • Paul Clapham
Saloon Keepers:
  • Tim Moores
  • Frits Walraven
  • Ron McLeod
  • Ganesh Patekar
  • salvin francis
Bartenders:
  • Tim Holloway
  • Carey Brown
  • Stephan van Hulst

f:validateLongRange with maximum value from database  RSS feed

 
Ranch Hand
Posts: 106
1
Chrome Java Netbeans IDE
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Good afternoon! I'm building an e-shop record store for a friend, he'll be selling his used vinyls. For some of the records he has multiple copies of, so there is a Stock quantity and naturally people cannot buy more copies than the available stock.

In the Cart bean, I have a column that shows the quantity people want, and the available stock from the database: (disregard for a minute the maximum=3 in the validator)

This works and I can see the available stock in the next column. The getStock() method takes the album id and returns an int.

Considering I want people to enter quantities up to the available stock, the following seems logical to me:


It's the exact same EL expression I'm using in the next column to display the available stock, only this time I want to retrieve the maximum value from the DB.

The application crashes though with the following stack:

I guess it passes a null value to the getStock() method, because the EJB that fetches the Stock entity from the DB, returns no result.

The StockService.findByID is:


What can I do to fix this? Considering that in one occasion it works and in the other it doesn't. Does the validator run before the other expressions so it rightfully passes a null value?
 
Ranch Hand
Posts: 210
2
Netbeans IDE
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Your log says that there was no result.  So you need to write code that will handle no result.  Right now it doesn't
 
Vasilis Souvatzis
Ranch Hand
Posts: 106
1
Chrome Java Netbeans IDE
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I don't get why it doesn't give a result the second time though.

When I have the following, it works without an issue


When I put

Why would it produce a result perfectly fine in the Stock column, but not in the validator? Both calls are in the same view.
 
Al Hobbs
Ranch Hand
Posts: 210
2
Netbeans IDE
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Not sure. But I think the real question is why are you making a call to the database in the view?
 
Al Hobbs
Ranch Hand
Posts: 210
2
Netbeans IDE
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Have you debugging it to see what the inputs are?
 
Vasilis Souvatzis
Ranch Hand
Posts: 106
1
Chrome Java Netbeans IDE
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Well, my reasoning is that if I query the DB for the stock, every user will always have the remaining quantity.

If user A buys the last item before user B completes the purchases, user B cannot proceed since there is no more stock available, A was faster and bought the last item.

Otherwise I'll probably have to check on purchase if there is stock and proceed with the purchase or cancel it.

Is there some other way I should be doing it?

----------------------

I realized this though; the getStock() method is called 4 times for each album when I enter the store view! I have two calls in the view (what I posted above), but it sysouts 4 times for each album.

Regarding the debugger, I tried it but I cannot bypass the correct calls to the Stock Service, in order to go the other page and see why it crashes.
 
Al Hobbs
Ranch Hand
Posts: 210
2
Netbeans IDE
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Probably should just check the quantity before sending data to the jsp.  If somebody else bought the last one you can just send that message
 
Al Hobbs
Ranch Hand
Posts: 210
2
Netbeans IDE
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Also, it's only checking it once so  it's not like you're making a live update or anything.  Unless soembody finishes a transaction in the time between a server request and the data being sent to the jsp there will be no difference.
 
Bartender
Posts: 20125
103
Android Eclipse IDE Linux
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
This is wrong:


EL is not a programming language for talking back and forth with the server and in any case View Templates should not contain application code, as it muddies the Separation of Concerns benefits of the Model/View/Controller architecture that JSF is based on.

This is the more proper way to code such constraints in JSF:


This pre-supposes that the backing bean has a simple "getItemsOnHand" property-get method. Because EL isn't intended to execute data code, it's intended to reference data properties.

Obviously that only works for a single value. Suppose you have a table of items being displayed and thus multiple values of items on hand. What to do then?

Well, first, use a dataTable with a DataModel. The dataTable is the View Template definition of how the data will display, the DataModel is the JSF object that wraps a collection of data (array, List, or other sequential collection) that will be displayed in the data.

Each element in the DataModel corresponds to one row in the displayed table. Since the dataTable has an internal cursor, you can code something like this:

caveat I'm hacking this out from memory, so there may be some minor corrections required here.

If you're using an ORM to retrieve inventory information in a flat record and you're lucky, you can make your DataModel wrap the returned list of inventory items, using the same POJO collection for both the JSF GUI model and the ORM persistence model. If not, use your persistence data to construct a collection of objects for a class you define that more closely matches what needs to be in the displayed table and populated it from the data you got from the database. In either case, you'd need a "getQoh" method in the POJO class used for the JSF GUI model.

Caution Do not succumb to the temptation to directly reference the raw data collection in the value of the dataTable tag. The DataModel adds valuable information that JSF can use to track what you are doing.

So much the JSF part of the problem. When you're doing something like a "real time" interactive order system, you still have the issue of what to do when multiple people are visiting the same page and (hopefully) ordering items from it. JSF is based on HTTP, and HTTP physically disconnects the client from the server except when an actual request/response (submit) operation is being done. Now you can use AJAX to update the displayed values in more or less real time without requiring the visitor to manually refresh the page periodically. That's up to you. However, ultimately, the only way to make sure that people don't buy more of something than you actually have requires your back-end database logic to use transactions to enforce data integrity. If people over-buy an object, the backend should detect this and signal a problem (typically by throwing an Exception), Here again, how you handle that is up to you, although one nice feature of JSF is that you can use its message facilities to place a message on the displayed order page and allow people to change their order without actually having to destroy everything and build a new page.
 
Vasilis Souvatzis
Ranch Hand
Posts: 106
1
Chrome Java Netbeans IDE
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Well... I knew I was doing something wrong but didn't expect to be so far out. I had completely mistaken how to use EL properly, I've seen code online to directly call beans and logic so I assumed it's OK to do so. That's why Al asked why I was calling the DB from the view.

And in fact I was uncertain if my approach was good because for each item in the datatable I would query the DB to get the stock, for many albums and/or users I would strain the app-DB communication. Besides, now that I think of it I haven't seen online stores live updating the remaining quantities. It most likely occurs at some page update or something.


Actually I think I can just use the Stock entities. Since the Stock is referencing the Album with a OneToOne association, instead of getting the albums and then asking for the stock of each album, I can retrieve just the stocks and they contain the albums anyway. This way I'm getting the data and the view is just referencing them in the datatable. If this doesn't work (out of the top of my head I don't see why it shouldn't) I can make a POJO with the album and its quantity for the datatable alone.

You mention transactions to ensure data integrity. I'm assuming a Stateless bean is enough right? Their methods initiate separate transactions if I'm not mistaken, so the purchases will not have problems. It's highly unlikely that two or more people will start their transactions at the exact same millisecond, therefore it's not easy for someone to over-purchase. And if the stock decreases before a user places an order, then yes I can use the messages to notify them.
 
Tim Holloway
Bartender
Posts: 20125
103
Android Eclipse IDE Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Lots of people get confused by JSF. They are used to code that "finds things" and "does stuff with it". JSF - like the Spring Framework (which plays very nicely with JSF) is based on Inversion of Control. Or, as I like to say, you sit at home and the goodies are delivered to you!

EL is not a programming language as such (hence the name "expression" language). So while you can (mis)code programming "statements" in EL, EL isn't intended for programming and attempts to make it look like a program often have unexpected consequences. As an example, EL is evaluated in the Restore View and Render Results stages of the JSF lifecycle, whereas submit actions are handled primarily in the Process Events stage. JSF Views and Models aren't really connected directly. Here again, JSF is supposed to be doing the work for you.

In fact, JSF is one of the purest implementations of the Model/View/Controller (MVC) concept for web applications. The View Template (xhtml) is digested into a Component Tree, which JSF refers to as it does its work. The Model(s) is/are JSF backing beans. You don't write Controllers in JSF, since the FacesServlet and tag libraries handle the Controller functions. Which, incidentally are exclusively concerned with making changes in the Model get updated in the View and vice versa. Apparently the NetBeans IDE wizard creates backing beans named "XxxxxController", but that is flat wrong. Action methods, incidentally, are outside of the MVC paradigm, but then every MVC system has something like that, since all MVC does is bounce changes in model and view back and forth and presumably sooner or later you'll either want to populate them or use their contents to do useful work (business logic).

As far as examples on the Internet go, the problem with the Internet is that not only is it a good place for find information, it's a great place to find mis-information and outdated information. For a long, long time, I routinely had to admonish people not to over-use bindings and listeners because before JSF got fully shaped, that was the mechanism that did (in a very cumbersome way) what more sophisticated parts of JSF do now, but the outdated info kept showing up at the top of people's search pages.

Don't skip the transactions. JEE multi-tasks heavily and a task can get interrupted while another task executes. The probability may be low that your update gets bitten, but Murphy's Law says that when it does happen, it will be at the worst possible time. If you do your updates transactionally and you're using an ORM, the ORM will generally detect cases where someone else updated the inventory between the time you fetched the data and the time you updated it and throw an exception.

My JSF webapps are usually using JPA with Spring so everything wires together nicely. The action method invokes a data update method in the top-level database logic tier. I usually have 2 persistence tiers, one for complex data and a lower-level one for single-table and tell Spring to make the methods transactional.

 
Tim Holloway
Bartender
Posts: 20125
103
Android Eclipse IDE Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Footnote.

I mentioned that EL is not intended to execute code, but to reference properties. But sharp-eyed people might point to EL actions. The action of a commandButton or commandLink is a method, not a property, as is the listener of an AJAX element.

But that doesn't mean that you use method-call syntax, even here.

That's because the format of these methods is rigidly determined. An action method is supposed to be invoked with no arguments (after all, the backing bean's properties have been updated before the action fired), and it should return a navigation string. An AJAX listener likewise has a specific signature - in this case, it gets passed an event object.

So you simply enter the name of the method. There are no arguments allowed and there's no ambiguity between whether it's an action or a property, so putting parentheses on the action attribute value is redundant.
 
Vasilis Souvatzis
Ranch Hand
Posts: 106
1
Chrome Java Netbeans IDE
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I know I started on the wrong foot with JSF three years ago, I had to write my thesis project and needed to have results as soon as possible. So I heavily relied on online code to make things work because I was on a deadline. Having no help from my supervisor didn't help also. So yes, I was exposed to a lot of old/old fashioned code. Most probably my misuse of EL comes from parameterized method calling, I used it weirdly in my thesis and probably stuck to me.

Lately I've been trying to shake off this misunderstanding and misuse, I like JSF and am quite productive with it although server-rendered frontends have moved aside last few years.

So far my approach to transactions seems to be working and the stock quantity is handled correctly. I will probably have to revisit it once I add online payments though, maybe keep the albums in a "reserved" state and remove them from stock or return them if the payment succeeds or not.
 
Tim Holloway
Bartender
Posts: 20125
103
Android Eclipse IDE Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Actually, using EL like it's a programming language was never the right way to do JSF. It's just a case of people trying to force JSF to behave like what they're used to and then publishing it on the Internet. The Internet, as I have said, is a great place for false information to get priority over the truth.
 
Can you really tell me that we aren't dealing with suspicious baked goods? And then there is this tiny ad:
RavenDB is an Open Source NoSQL Database that’s fully transactional (ACID) across your database
https://coderanch.com/t/704633/RavenDB-Open-Source-NoSQL-Database
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!