How to set progress bar value using jsp - java

I am trying to make a servlet to download files online. For this, I have made a progress bar element in jsp.
<progress id="p1" max="100" value="0"><span>0</span>%</progress>
and the java script code to update the progress value:
function setProgress(value)
{
var progressBar = document.getElementById("p1");
progressBar.value = value;
progressBar.getElementsByTagName('span')[0].textContent = value;
}
Now, In the servlet code to change the progress:
InputStream is = ..........;
byte[] bytes = new byte[size*1024];
int read = in.read();
for(int j=0;read!=-1;j++)
{
bytes[j] = (byte)read;
setProgress((int)getProgressDownload(bytes.length));
read = in.read();
}
public float getProgressDownload(int dsize)
{
return ((float)dsize/tsize)*100;//tsize is total file's size;
}
public void setProgress(int value)
{
try
{
response.getWriter().write("<script>");
response.getWriter().write("setProgress(\"p1\","+value+");");
response.getWriter().write("</script>");
}
catch(Exception e)
{
e.printStackTrace();
}
}
Now the problem is that is makes the HTML code lengthy because for every byte it will print a script code.
What should I do to prevent this?
Thanks for help

Hi first I think you should store the process in session. And then using ajax call you can regularly update the progress bar using response received from below some servlet. Add the mapping and all I am just writing the doGet stuff..
Also I assume URL mapping as 'progressServlet' for this particular servlet..
Below is doGet method
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String downloadId = "longProcess_" + request.getParameter("downloadId");
LongProcess longProcess = (LongProcess) request.getSession().getAttribute(downloadId);
int progress = longProcess.getProgress();
response.setContentType("application/json");
response.setCharacterEncoding("UTF-8");
response.getWriter().write(String.valueOf(progress));
}
And then in JS you can use setTimeout() /setInterval() to call checkProgress method given below at certain intervals and stop calling if progress received is 100% complete. You can use this to repeatedly fire Ajax requests to request current status of the progress.
var refreshprogessbar = setInterval(checkProgress, 10000);// 10 seconds
function checkProgress() {/*pass the actual id instead of 12345*/
$.getJSON('progressServlet?downloadId=12345', function(progress) {
if(progress == 100){clearInterval(refreshprogessbar);}
setProgress(progress);
});
}
LongProcess is basically the class you use to keep track of the on going process. Below is the example of one of such:
class LongProcess extends Thread {
private int progress;
public void run() {
while (progress < 100) {
try { sleep(1000); } catch (InterruptedException ignore) {}
progress++;
}
}
public int getProgress() {
return progress;
}
}
I am just incrementing the progress filed member but you can have a setProgress() method and add logic to increase the progress.

Related

is Eclipse/Californium CoAP observer much slower than Aiocoap observer?

I'm trying to build a system in which I can connect some devices to a server over the internet.
I want to stream some data over CoAP (10-30FPS), frame size = 3KB.
Firstly, I used Aiocoap, it sends up to 100FPS but uses too much CPU,
requests are NON, got low lose rate in Aiocoap,
while Eclipse/Californium could not send more than 3FPS,
when i use higher FPS, either I receive only the first block of each message or receiving nothing, also not ordered most of the times.
I was wondering if this is the real performance of Californium or am I using it in a wrong way?
I will share some code:
server.java
static class CoapObserverServer extends CoapResource {
int i = -1;
public CoapObserverServer() {
super("alarm");
setObservable(true); // enable observing
setObserveType(Type.NON); // configure the notification type to CONs
getAttributes().setObservable(); // mark observable in the Link-Format
System.out.println(this);
// schedule a periodic update task, otherwise let events call changed()
//new Timer().schedule(new UpdateTask(), 0, 1000/2);
}
private class UpdateTask extends TimerTask {
#Override
public void run() {
changed(); // notify all observers
}
}
#Override
public void handleGET(CoapExchange exchange) {
// the Max-Age value should match the update interval
exchange.setMaxAge(1);
//++i;
int leng = 2000;
String s = "" + i + "-" + fillString('X', leng - 1 - Integer.toString(i).len>
exchange.respond(s);
}
public static String fillString(char fillChar, int count){
// creates a string of 'x' repeating characters
char[] chars = new char[count];
while (count>0) chars[--count] = fillChar;
return new String(chars);
}
#Override
public void handleDELETE(CoapExchange exchange) {
delete(); // will also call clearAndNotifyObserveRelations(ResponseCode.NOT_>
exchange.respond(ResponseCode.DELETED);
}
#Override
public void handlePUT(CoapExchange exchange) {
exchange.accept();
int format = exchange.getRequestOptions().getContentFormat();
if (format == MediaTypeRegistry.TEXT_PLAIN) {
// ...
String plain = exchange.getRequestText();
try{
i = Integer.valueOf(plain);
} catch(NumberFormatException ex){
System.out.println("error converting string"+ plain);
}
exchange.respond(ResponseCode.CHANGED);
changed(); // notify all observers
}
}
Observer.java
private static final File CONFIG_FILE = new File("Californium3.properties");
private static final String CONFIG_HEADER = "Californium CoAP Properties file for client";
private static final int DEFAULT_MAX_RESOURCE_SIZE = 2 * 1024 * 1024; // 2 MB
private static final int DEFAULT_BLOCK_SIZE = 512;
static {
CoapConfig.register();
UdpConfig.register();
}
private static DefinitionsProvider DEFAULTS = new DefinitionsProvider() {
#Override
public void applyDefinitions(Configuration config) {
config.set(CoapConfig.MAX_RESOURCE_BODY_SIZE, DEFAULT_MAX_RESOURCE_SIZE);
config.set(CoapConfig.MAX_MESSAGE_SIZE, DEFAULT_BLOCK_SIZE);
config.set(CoapConfig.PREFERRED_BLOCK_SIZE, DEFAULT_BLOCK_SIZE);
}
};
private static class AsynchListener implements CoapHandler {
#Override
public void onLoad(CoapResponse response) {
System.out.println( response.getResponseText() );
}
#Override
public void onError() {
System.err.println("Error");
}
}
/*
* Application entry point.
*/
public static void main(String args[]) {
Configuration config = Configuration.createWithFile(CONFIG_FILE, CONFIG_HEADER, DEFAULTS);
Configuration.setStandard(config);
URI uri = null; // URI parameter of the request
if (args.length > 0) {
// input URI from command line arguments
try {
uri = new URI(args[0]);
} catch (URISyntaxException e) {
System.err.println("Invalid URI: " + e.getMessage());
System.exit(-1);
}
CoapClient client = new CoapClient(uri);
client.useNONs();
// observe
AsynchListener asynchListener = new AsynchListener();
CoapObserveRelation observation = client.observe(asynchListener);
// User presses ENTER to exit
System.out.println("Press ENTER to exit...");
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
try { br.readLine(); } catch (IOException e) { }
System.out.println("Exiting...");
observation.proactiveCancel();
}
So i'm controlling the FPS by sending PUT requests with a server that has a counter 0-50.
Not sure, what your doing.
That seems to be wired and not related to RFC7252 nor RFC7641.
CoAP is designed for REST, I don't see any benefit in using it for video streaming.
Using Eclipse/Californium on a Intel n6005 with 16GB RAM, the CoAP/DTLS server runs on about 60000 requests/second. The benchmark uses 2000 clients in parallel.
See also Eclipse/Californium - Benchmarks j5005
Using only one client with CON requests, the performance is mainly limited by the RTT. 30 requests/second should work, if that RTT is accordingly small.
Using NON requests doesn't really help. CoAP RFC7252 defines two layers, a messaging layer and an application layer. NON affects only the messaging layer, but a NON request will wait for it's response, if NSTART-1 should be used.
If your RTT is the issue, you may try to escape that either using requests with "No Server Response" (RFC7967) or multiple NON responses (RFC7641). The first is not intended for fast requests, the second is more a work-around of the initial statement, that CoAP is REST not video-streaming.
So, what is your RTT?

How to add results of Facebook Graph api to array list in Java

I am using the Facebook graph api to find out what pages a user is apart of. When the query comes back with a json object it has what I need but, for some reason it doesn't want to add to my array list. The correct value is printed in log.d it seems to skip my arraylist for some reason. Any ideas?
Find page function
private ArrayList<String> foundPages;
private JSONObject jsonObject;
public ArrayList<String> findPages()
{
accessToken = AccessToken.getCurrentAccessToken();
foundPages = new ArrayList<>();
GraphRequest request = GraphRequest.newGraphPathRequest(
accessToken,
"/me/accounts",
new GraphRequest.Callback() {
#Override
public void onCompleted(GraphResponse response) {
try {
jsonObject = response.getJSONObject();
for(int i=0; i < jsonObject.getJSONArray("data").length(); i++)
{
page = response.getJSONObject().getJSONArray("data").getJSONObject(i).getString("name");
Log.d("viewmodel",page);
foundPages.add(page);
}
} catch (JSONException e) {
e.printStackTrace();
}
}
});
request.executeAsync();
return foundPages;
}
There is a common way to solve this problem, which is to define a callback method which will return these values to you, AFTER they have been populated by the call, which goes something like this (my java is rusty, bear with me...)
define an interface :
interface Callback{
void apiResponseCallback(ArrayList<Page> result);//whatever your model is, make the array of that type
}
then, in your normal findPages method, change it to this:
public void findPages(Callback callback) {
//
//
........
for(int i=0; i < jsonObject.getJSONArray("data").length(); i++)
{
page = response.getJSONObject().getJSONArray("data").getJSONObject(i).getString("name");
Log.d("viewmodel",page);
foundPages.add(page);
}
callback.apiResponseCallback(foundPages);//here we are returning the data when it is done
}
then, when you call findPages
findPages(new Callback() {
#Override
public void apiResponseCallback(ArrayList<Page> result) {
here, this result parameter that comes through is your api call result to use, so result will be your populated pages to use.
}
});
}
sake of completeness:
public void findPages(Callback callback)
{
accessToken = AccessToken.getCurrentAccessToken();
foundPages = new ArrayList<>();
GraphRequest request = GraphRequest.newGraphPathRequest(
accessToken,
"/me/accounts",
new GraphRequest.Callback() {
#Override
public void onCompleted(GraphResponse response) {
try {
jsonObject = response.getJSONObject();
for(int i=0; i < jsonObject.getJSONArray("data").length(); i++)
{
page = response.getJSONObject().getJSONArray("data").getJSONObject(i).getString("name");
Log.d("viewmodel",page);
foundPages.add(page);
}
callback.apiResponseCallback(foundPages);
} catch (JSONException e) {
e.printStackTrace();
}
}
});
request.executeAsync();
}
Yep. This here:
request.executeAsync();
triggers an asynchronous request. But your "current" thread simply continues to do:
return foundPages;
and it returns an empty list.
That list gets later filled, but at the moment in time when that method returns, that list is still empty. Or just gets filled. Who knows, as it gets filled asynchronously, at some unknown point in the future.
A solution could be to have some other variable/field that tells you the data has arrived and pushed into the list.
Alternatively, that method could just make a synchronous request, simply block the caller from progressing until the data has arrived.
You see, you can't have it both ways: when you don't wait for your results to arrive, you shouldn't expect them to be available immediately.

ScheduledExecutorService task will be executed by multi-thread

This makes me really curious.There is a button which sends a simple post request by ajax on a jsp page,and I use a RESTFUL method to handle this request,but that method will be executed twice or three times.This will only happen on CentOS 7.3,on my laptop I use windows10, multi-thread will not happen.I have searched on Google but nothing helpful
has been found.Here are the codes:
asset.jsp:
<button class="btn btn-default btn-sm" title="allDoMi">
<i class="fa fa-arrow-down">allDoMi</i>
</button>
$("button[title='allDoMi']").click(function () {
var dataparam = "version=1";
if (!confirm('confirm all DoMi?'))
return;
//ajax request
$.ajax({
contentType: "application/json",
url: serviceurl.baseurl + "/asset/doMiAction",
data: dataparam,
beforeSend: function () {
//do nothing
},
error: function () {
//do nothing
},
success: function (info) {
//do nothing
}
});
});
Asset.java
#Service
#Path("/asset")
public class AssetRest {
#Path("/doMiAction")
#POST
#Produces({ MediaType.APPLICATION_JSON,
MediaType.APPLICATION_XML })
public RestfulResult doMiAction(#FormParam("version") String
version) {
logger.info("doMiAction method began....");
//package data for duMiSyncDtos,here only for test
List<DuMiSyncDto> duMiSyncDtos =new List<>();
//this url is for http simulation using HttpURLConnection
final String dumiUrl = "http://someip/someurl";
final Map<String, List<DuMiSyncDto>> map;
//only continue when list is not empty
if (!duMiSyncDtos.isEmpty()) {
//this method used for sync data in a certain order
map = groupList(duMiSyncDtos);
SortedSet<String> ss = new TreeSet<>(map.keySet());
final Iterator<String> iter = ss.iterator();
final ScheduledExecutorService ticker = Executors.newSingleThreadScheduledExecutor();
logger.info("NEW A SINGLETHREADSCHEDULEDEXECUTOR");
//retrieve data from a .property file,I set it 20000,therefore the job will be executed in every 20 seconds
final int DELAY = NumberUtils.toInt(WebUtils.getConfigValue("dumi.delay"));
ticker.scheduleWithFixedDelay(new Runnable() {
private int count;
public void run() {
logger.info("BEGIN RUN METHOD:"+System.identityHashCode(AssetRest.this));
if(iter.hasNext()) {
try {
List<DuMiSyncDto> value = map.get(iter.next());
//this method used for simulating a httprequest using HttpURLConnection to invoke a remote service to get the result info which forms in a JSON string format
String resultmsg = getDuMiReturnMessage(dumiUrl,value);
if(resultmsg!=null && !resultmsg.contains("\"code\":\"0000\"")) {
logger.info("Return code is "+resultmsg+",the sync work will be terminated.");
ticker.shutdown();
return;
}
//this method used for showing some useful infomation on the console using log4j
showSyncInfomation(value);
//this method used for count how many items have been synchronized successfully
int currentcount = getSyncCount(resultmsg);
count += currentcount ;
logger.info("current sync data:"+currentcount+",summing data"+count+"");
} catch (Exception e) {
logger.error("method[doMiAction]...executing schedule:",e);
}
} else {
ticker.shutdown();
}
}
}, 0, DELAY, TimeUnit.MILLISECONDS);
}
}
After I click the button,all the log info will be shown on Putty console for two or three times,yet I have clicked that button for only ONCE!I have tested for several times,it will happen,but in windows on my laptop,this will not happen at all.Here is a detail might be help:previously the implementation for timed execution is not like this,it has been written like :
for(DuMiSyncDto dto:duMiSyncDtoList){
//do the business code
Thread.sleep(20000);
}
Because there is database synchronization from the remote service,I need to control the interval time not too soon between every two operations:execute in every 20 seconds and 100 data at a time.In this situation,the multi-thread problem occurs,I thought it may be the for loop which aroused so I change the way using a JDK API instead but issues were still there.So WHY all of these?
---------------------------first edit------------------------------------------
private int getSyncCount(String resultmsg) {
int count = 0;
JSONObject obj = JSONObject.fromObject(resultmsg);
String message = obj.getString("message");
if(!WebUtils.isEmpty(message)) {
String[] arr = message.split(" ");
if(arr!=null && arr.length>1) {
count += Integer.parseInt(arr[1].trim());
}
}
logger.info("currentThreadName:"+Thread.currentThread().getName());
return count;
}
Notice in this method,I log the current thread name,and it shows :
...
currentThreadName:pool-1-thread-1
currentThreadName:pool-2-thread-1
currentThreadName:pool-3-thread-1
...
when there are 3 threads.

How to send custom graph data to MCStats every hour?

I have been working on a plugin and have gotten some really interesting data with it, I am trying to add a custom graph and have succeeded on getting the graph to appear with the name I set in code on MCStats.
My plugin is here and recreates the Dense Ores Mod.
I would like to send block mined data on an hourly basis. This is what I have in my onEnable so far:
try {
Metrics metrics = new Metrics(this);
Graph blocksMinedGraph = metrics.createGraph("Extra items from blocks");
blocksMinedGraph.addPlotter(new Metrics.Plotter("Coal Ore") {
#Override
public int getValue() {
return coalMined;
}
});
blocksMinedGraph.addPlotter(new Metrics.Plotter("Iron Ore") {
#Override
public int getValue() {
return ironMined;
}
});
metrics.start();
} catch (IOException e) {
getLogger().info(ANSI_RED + "Metrics have been unable to load for: DenseOres" + ANSI_RESET);
}
This has successfully created a new graph on my MCStats page called 'Extra items from blocks' although I have been unable to populate it thus far. I have tried but cannot work out how to send the data.
Connected to this question, when sending the data, will I have to keep a count of the values in a file somewhere so they persist between reloads and server restarts?
I appear to have solved it by placing the blocksMinedGraph.addPlotter(...) parts in an async repeating task.
Here is the code with the repeating task in place, the graphs on MCStats take forever to update though.
try {
Metrics metrics = new Metrics(this);
if (!metrics.isOptOut()) {
final Graph blocksMinedGraph = metrics.createGraph("Extra items from blocks (Since v2.3)");
Bukkit.getScheduler().runTaskTimerAsynchronously(this, new Runnable() {
public void run() {
getLogger().info("Graph data sent");
blocksMinedGraph.addPlotter(new Metrics.Plotter("Coal Ore") {
#Override
public int getValue() {
return coalMined;
}
});
blocksMinedGraph.addPlotter(new Metrics.Plotter("Iron Ore") {
#Override
public int getValue() {
return ironMined;
}
});
}
}, DELAY, INCREMENT);
getLogger().info("Metrics started");
metrics.start();
}
} catch (IOException e) {
getLogger().info(ANSI_RED + "Metrics have been unable to load for: DenseOres" + ANSI_RESET);
}

Servlet 3: Async - cant PUSH partial response

I am using Tomcat 7. When my asynchronous servlet tries to PUSH partial response to client at different intervals, it does not work.. The response gets flushed only after the whole response is ready.
How to PUSH partial response?
Here is my code
#WebServlet(urlPatterns={"/home"} , name="asynch", asyncSupported=true)
public class CometServlet extends HttpServlet {
public void doGet(final HttpServletRequest request, final HttpServletResponse response) throws IOException, ServletException
{
final AsyncContext ac = request.startAsync();
new MyThread(ac).start();
}
}
What MyThread does is it will write numbers from 1 to 10 to the reponse object at regular intervals.
class MyThread extends Thread
{
AsyncContext ac;
public MyThread( AsyncContext ac ) {
this.ac = ac;
}
public void run()
{
int i =2 ;
while( i < 10 )
{
try
{
ac.getResponse().getWriter().print(i + "\n" );
ac.getResponse().getWriter().flush();
ac.getResponse().flushBuffer();
Thread.sleep(1000);
}
catch (Exception e) {
System.out.println("ccttt " + e);
}
i++;
}
ac.complete();
}
}
And the page that requests the servlet
<script type="text/javascript">
function show()
{
var xml = new XMLHttpRequest();
xml.open("GET", "http://localhost:8080/Comet/home", true );
xml.onreadystatechange=function()
{
if (xml.readyState== 3|| xml.readyState == 4 ) {
document.getElementById("dynamicContent").innerHTML=xml.responseText;
}
}
xml.send(null);
}
</script>
<input type="button" value="show" onclick="show()"/>
<div id="dynamicContent"> </div>
After about 10 seconds I see the complete response on the browser. But I want to see the partial outputs every second.
All i want to learn is how to PUSH partial response with Servlet 3 API.
Can someone answer this question?
Please see my answer for this exact same problem mentioned in another question.
If you still face this problem after following the instructions in that answer, do let me know.

Categories