I want to create an online test system, so i need a timer. When user start the test the timer will start counting down. But when user go to next question refresh the page the timer will still running. How can I do that any suggestion?
You can use PrimeFaces Poll option.
The counter will always be saved on the server.
You can also use PrimeFaces Extensions, they have timer in their API.
Example: you put start of the test into #SessionScoped bean, then calculate seconds remaining which will be used as an input to <pe:timer> element:
#SessionScoped
public class UserData {
private Date testStart;
/* getters and setters for testStart */
public int secondsRemaining() {
//calculate seconds remaining until end of the test from this.testStart
return secondsRemaining;
}
}
and then your test.xhtml would contain element
Time remaining: <pe:timer format="HH:mm:ss"
timeout="#{userData.secondsRemaining()}"/>
Related
Can I run Service in background thread?
I want to load data from database and during loading data i want progress bar to be indicating progress. First I have created task, run it in background thread and then update progress bar according to this task. However, I found out that this Task is not reusable, so next time i hit the button, it didn't work. Later on, I fount out that Service can run Tasks multiple times, So i have encapsulated those tasks inside of Service.
Now it works great - every time i hit button, table is reloaded - except progress bar is not moving.
How can I reach desired result?
Okay... Here is completed code: https://mega.nz/#!yUsjgJyZ!DHfuBqsujAHurS-pQ_W5y8BAflOtvxsm48goRPkDsxA
First, i want to tell you what is my goal:
When I run program, i want the progress bar to be in indeterminate state. After pressing the button, i want progress bar to reflect progress of Service. After finishing the Service, i want the progress bar to be completed (100%).
Here is what i have found. It looks like service automatically runs it's task on background thread. I have built a "sand box" program where i was playing with services and progress bar. The program comprised of progress bar, two text fields with two buttons above them. First button can start service_countTo100 and second button can run service_getActualCount.
Now in fxml file i set progress bar to indeterminate default state. After pressing the button1, a counting has started (displayed in text_field1) and progress bar has changed according to actual progress. After pressing button2, actual value of count is displayed in text_field2. And here comes some issues. To demonstrate the issues, i will show you source code of Service:
// Create the service
public static Service<Integer> serviceTo100 = new Service<Integer>() {
#Override
protected Task<Integer> createTask() {
Task<Integer> taskTo100 = new Task<Integer>() {
#Override protected Integer call() throws Exception {
int iterations;
updateProgress(-1, 100);
for (iterations = 0; iterations < 100; iterations++) {
if (isCancelled()) {
updateMessage("Cancelled");
break;
}
updateMessage("Iteration " + iterations);
updateProgress(iterations, 100);
// Now block the thread for a short time, but be sure
// to check the interrupted exception for cancellation!
try {
Thread.sleep(100);
} catch (InterruptedException interrupted) {
if (isCancelled()) {
updateMessage("Cancelled");
break;
}
}
}
//udpateProgress(100, 100);
return iterations;
}
};
return taskTo100;
}
};
As you can see, there is a simple loop which counts from 0 to 100 and there is also a updateProgress(iterations, 100); statement which updates progress. This service is located in Services class. In FXMLDocumentController.java is method called runService(Service service) defined as this:
public void runService(Service service){
service.start();
progressBar.progressProperty().bind(service.progressProperty());
service.setOnSucceeded((event) -> {
service.reset();
progressBar.progressProperty().unbind();
progressBar.setProgress(1);
});
}
The initialize looks like this:
#Override
public void initialize(URL url, ResourceBundle rb) {
btn_start1.setOnAction((event) -> {
Service service = Services.serviceTo100;
runService(service);
txt_field1.textProperty().bind(service.messageProperty());
System.out.printf("something\n");
});
.
.
.
}//end of initialize
Now the most interesting thing (at least for me, novice) comes into play.
In service definition, you can notice commented line //updateProgress(100,100). That was my try to set progress bar to completed state when counting has stopped. But java ignored that line. I tried to put System.out.print("Something"); and it worked, but updateProgress(100, 100) didn't. When counting has finished, progress bar was set to it's default state defined in fxml file, which was indeterminate.
Conclusion: Service class creates task defined inside of it and after task is completed, the task doesn't exists anymore, thus, there is no progress to be bound with progress bar.
Even though task does not exists anymore, you cannot set progress of the bounded progress bar with setProgress(double double) method. You first need to unbound it.
Now I got what i needed:
You run the program, progress bar is in indeterminate state, waiting for hit. You hit the button, service starts counting up to 100 and progress bar is progressing according to progressProperty of service. When counting is done, Progress bar is set to indeterminate state again, waiting for another start.
I am invoking a method from rendered attribute, where I noticed that the method is triggered multiple times in RENDER_RESPONSE phase.
It was also noticed that the method was trigered many times in other phases (APPLY_REQUEST_VALUES, PROCESS_VALIDATIONS etc.) also.
I saw a related query (Why is the getter called so many times by the rendered attribute?) where the reason behind these calls were told.
Is there a way where we can control this, so that the method is invoked only once.
My usage
<rich:panelMenuItem label="Menu1" actionListener="#{testMenuMB.panelMenuClickedAjax}" rendered="#{testMenuMB.checkForRendering('RoleA,RoleB')}"></rich:panelMenuItem>
public boolean checkForRendering(String rolesString){
System.out.println("Roles-->"+rolesString+FacesContext.getCurrentInstance().getCurrentPhaseId());
boolean authorized = false;
String [] rolesArray = rolesString.split(",");
for (String string : rolesArray) {
if(string!=null && accesibleRolesMap.containsKey(string)){
authorized = true;
break;
}
}
return authorized;
}
You cannot control the number of times the method is called, its framewroks lifecycle. You should find appropriate place to set the boolean value e.g. on command click action method, use this boolean value in render method so that logic is executed once in action method and only boolean is returned.
Other thing is you can protect the logic with if condition by probing for current lifecycle phase for render response.
if(FacesContext.getCurrentInstance().getRenderResponse()){
//logic
}
But I'll prefer first option.
I am developing pagination logic using JSF1.2 and in the process I have 4 links for first, previous, next and last pages corresponding to the results. I enter the search criteria in the Search page and click submit to get some records. I have a view link corresponding to each of the records to see the complete details. So I have two Managed beans one for Search/pagination functionality and other for View complete record details.
Whats the problem then?
When I search for the records the pagination works completely fine. However when I view the details of a record and come back to search page, I find that every time I click the next button the next() method is getting called twice.
Is there any solution for this?
The code is as follows:-
Inside search:-
<h:commandLink value="#{msg['heading.nextLink']}"
binding="#{searchRoutesForView.nextLink}"
actionListener="#{searchRoutesForView.next}">
</h:commandLink>
Inside SearchManagedbean:-
public void next(ActionEvent actionEvent) {
if ((pointer + noOfRecordsToBeDisplayed) >= readConfig.length) {
readRoutingResponse.setReadConfig(Arrays.copyOfRange(readConfig,
pointer, readConfig.length));
pointer = readConfig.length;
System.out.println("pointer inside next =" + pointer);
setOrDisableLinks(false, false, true, true);
} else {
readRoutingResponse.setReadConfig(Arrays.copyOfRange(readConfig,
pointer, pointer + noOfRecordsToBeDisplayed));
pointer += noOfRecordsToBeDisplayed;
System.out.println("pointer inside next -- else =" + pointer);
setOrDisableLinks(false, false, false, false);
}
}
Please have a look at the lifecyle of JSF
Below approach may not be the best one..
public void next(ActionEvent actionEvent)
{
if((pointer + noOfRecordsToBeDisplayed) >= readConfig.length) && (isVisitedOnce == false))
{
visitedOnce = true //set one boolean indicating this method is already visited
}
}
This will not work if bean is in Request scope.
Ok, I'm working on my final dilemna for my project. The project is an IPv4 endpoint updater for TunnelBroker's IPv6 tunnel. I have everything working, except for the timer. It works, however if the user disables the "automatic update" and reenables it, the application crashes. I need the timer to be on an thread outside of the EDT (in such a way that it can be destroyed and recreated when the user unchecks/checks the automatic update feature or changes the amount of time between updates).
What I'm pasting here is the code for the checkbox that handles automatic updates, and the timer class. Hopefully this will be enough to get an answer on how to do this (I'm thinking either it needs to be a worker, or use multi-threading--even though only one timer will be active).
private void jCheckBox1ItemStateChanged(java.awt.event.ItemEvent evt) {
// TODO add your handling code here:
// if selected, then run timer for auto update
// set time textbox to setEditable(true) and get the time from it.
// else cancel timer. Try doing this on different
// class to prevent errors from happening on reselect.
int updateAutoTime = 0;
if (jCheckBox1.isSelected())
{
updateAutoTime = Integer.parseInt(jTextField4.getText())*60*1000;
if (updateAutoTime < 3600000)
{
updateAutoTime = 3600000;
jTextField4.setText(new Integer(updateAutoTime/60/1000).toString());
}
updateTimer.scheduleAtFixedRate(new TimerTask() {
public void run()
{
// Task here ...
if (jRadioButton1.isSelected())
{
newIPAddress = GetIP.getIPAddress();
}
else
{
newIPAddress = jTextField3.getText();
}
strUsername = jTextField1.getText();
jPasswordField1.selectAll();
strPassword = jPasswordField1.getSelectedText().toString();
strTunnelID = jTextField2.getText();
strIPAddress = newIPAddress;
if (!newIPAddress.equals(oldIPAddress))
{
//fire the tunnelbroker updater class
updateIP.setIPAddress(strUsername, strPassword, strTunnelID, strIPAddress);
oldIPAddress = newIPAddress;
jLabel8.setText(newIPAddress);
serverStatus = updateIP.getStatus().toString();
jLabel6.setText(serverStatus);
}
else
{
serverStatus = "No IP Update was needed.";
jLabel6.setText(serverStatus);
}
}
}, 0, updateAutoTime);
}
else
{
updateTimer.cancel();
System.out.println("Timer cancelled");
System.out.println("Purged {updateTimer.purge()} tasks.");
}
}
As I mentioned, this works once. But if the user deselects the checkbox, it won't work again. And the user can't change the value in jTextField4 after they select the checkbox.
So, what I'm looking for is this:
How to make this so that user can select and deselect the checkbox as they want (even if it's multiple times in a row).
How to make this so the user can change the value in jTextField4, and have it automatically cancel the current timer, and start a new one with the new value (I haven't done anything with the jTextField4 at all, so I'll have to create an event to cover it later).
Thanks, and have a great day:)
Patrick.
Perhaps this task would be better suited to a javax.swing.Timer. See Timer.restart() for details.
Note that Timer is relatively inaccurate over long time periods. One way to account for that is to have it repeat frequently but perform it's assigned task only one a certain time has been reached or passed.
Would I be able to wrap everything in the "task" portion of the call to Swing Timer, or do I have to create another class that handles the task?
You might want to wrap the grunt work in a SwingWorker to ensure the EDT is not blocked.
..I'm assuming that I would have to create the timer as a class-level declaration .. correct?
Yes, that is what I was thinking.
Im using subsonic 2.2
I tried asking this question another way but didnt get the answer i was looking for.
Basically i ususally include validation at page level or in my code behind for my user controls or aspx pages. However i haev seen some small bits of info advising this can be done within partial classes generated from subsonic.
So my question is, where do i put these, are there particular events i add my validation / business logic into such as inserting, or updating. - If so, and validation isnt met, how do i stop the insert or update. And if anyone has a code example of how this looks it would be great to start me off.
Any info greatly appreciated.
First you should create a partial class for you DAL object you want to use.
In my project I have a folder Generated where the generated classes live in and I have another folder Extended.
Let's say you have a Subsonic generated class Product. Create a new file Product.cs in your Extended (or whatever) folder an create a partial class Product and ensure that the namespace matches the subsonic generated classes namespace.
namespace Your.Namespace.DAL
{
public partial class Product
{
}
}
Now you have the ability to extend the product class. The interesting part ist that subsonic offers some methods to override.
namespace Your.Namespace.DAL
{
public partial class Product
{
public override bool Validate()
{
ValidateColumnSettings();
if (string.IsNullOrEmpty(this.ProductName))
this.Errors.Add("ProductName cannot be empty");
return Errors.Count == 0;
}
// another way
protected override void BeforeValidate()
{
if (string.IsNullOrEmpty(this.ProductName))
throw new Exception("ProductName cannot be empty");
}
protected override void BeforeInsert()
{
this.ProductUUID = Guid.NewGuid().ToString();
}
protected override void BeforeUpdate()
{
this.Total = this.Net + this.Tax;
}
protected override void AfterCommit()
{
DB.Update<ProductSales>()
.Set(ProductSales.ProductName).EqualTo(this.ProductName)
.Where(ProductSales.ProductId).IsEqualTo(this.ProductId)
.Execute();
}
}
}
In response to Dan's question:
First, have a look here: http://github.com/subsonic/SubSonic-2.0/blob/master/SubSonic/ActiveRecord/ActiveRecord.cs
In this file lives the whole logic I showed in my other post.
Validate: Is called during Save(), if Validate() returns false an exception is thrown.
Get's only called if the Property ValidateWhenSaving (which is a constant so you have to recompile SubSonic to change it) is true (default)
BeforeValidate: Is called during Save() when ValidateWhenSaving is true. Does nothing by default
BeforeInsert: Is called during Save() if the record is new. Does nothing by default.
BeforeUpdate: Is called during Save() if the record is new. Does nothing by default.
AfterCommit: Is called after sucessfully inserting/updating a record. Does nothing by default.
In my Validate() example, I first let the default ValidatColumnSettings() method run, which will add errors like "Maximum String lenght exceeded for column ProductName" if product name is longer than the value defined in the database. Then I add another errorstring if ProductName is empty and return false if the overall error count is bigger than zero.
This will throw an exception during Save() so you can't store the record in the DB.
I would suggest you call Validate() yourself and if it returns false you display the elements of this.Errors at the bottom of the page (the easy way) or (more elegant) you create a Dictionary<string, string> where the key is the columnname and the value is the reason.
private Dictionary<string, string> CustomErrors = new Dictionary<string, string>
protected override bool Validate()
{
this.CustomErrors.Clear();
ValidateColumnSettings();
if (string.IsNullOrEmpty(this.ProductName))
this.CustomErrors.Add(this.Columns.ProductName, "cannot be empty");
if (this.UnitPrice < 0)
this.CustomErrors.Add(this.Columns.UnitPrice, "has to be 0 or bigger");
return this.CustomErrors.Count == 0 && Errors.Count == 0;
}
Then if Validate() returns false you can add the reason directly besides/below the right field in your webpage.
If Validate() returns true you can safely call Save() but keep in mind that Save() could throw other errors during persistance like "Dublicate Key ...";
Thanks for the response, but can you confirm this for me as im alittle confused, if your validating the column (ProductName) value within validate() or the beforevalidate() is string empty or NULL, doesnt this mean that the insert / update has already been actioned, as otherwise it wouldnt know that youve tried to insert or update a null value from the UI / aspx fields within the page to the column??
Also, within asp.net insert or updating events we use e.cancel = true to stop the insert update, if beforevalidate failes does it automatically stop the action to insert or update?
If this is the case, isnt it eaiser to add page level validation to stop the insert or update being fired in the first place.
I guess im alittle confused at the lifecyle for these methods and when they come into play