Android application exits without any exception - java

I'm building an application that shows in a WebView some remote data that is cached in SQLite db. The data is being requested by JavaScript function from WebView via JavaScript interface.
When user types into an input element on the page, JavaScript function requests search result by calling Java function, which in turn fires a sql query. Results are then packaged in suitable JSON format and returned.
Fetching data works OK unless you type very quickly. If you type quick enough after few key presses the app quits WITHOUT any exceptions being thrown, it just goes back to home screen.
I have managed to narrow down the cause - commenting out the call to .query method prevents crashing, but renders app useless.
Is there a way to check what caused application to quit, another log or tool that could help?
Java function code:
public Lot[] getLotList(String query, int limitCount) {
...
...
String[] resultColumns = new String[] { LotsSearch._ID };
String queryWhere = LotsSearch.TABLE_NAME + " MATCH ?";
String[] queryArgs = new String[] { query + "*" };
String sortOrder = LotsSearch.COLUMN_NAME_NUMBER + " ASC, " + LotsSearch.COLUMN_NAME_TITLE + " ASC";
String limit = null;
Cursor cursor = null;
if (limitCount != -1)
limit = "0," + limitCount;
try {
cursor = mDb.query(LotsSearch.TABLE_NAME, resultColumns, queryWhere, queryArgs, null, null, sortOrder, limit);
if (cursor != null && cursor.moveToFirst()) {
result = new Lot[cursor.getCount()];
try {
int idColumnIndex = cursor.getColumnIndexOrThrow(LotsSearch._ID);
int lotId;
Lot lot;
do {
lotId = cursor.getInt(idColumnIndex);
lot = mLots.get(lotId);
if (lot != null)
result[index++] = lot;
} while (cursor.moveToNext());
} catch (IllegalArgumentException e) {
e.printStackTrace();
}
}
} catch (SQLiteException e) {
e.printStackTrace();
} finally {
if (cursor != null)
cursor.close();
}
...
...
return result;
}
UPDATE:
I have discovered that there is another log that could be accessed by issuing
logcat -b events
when the app crashes there is just one entry
I/am_proc_died( 59): [11473,com.example.app]
and when the app exits gracefuly this log shows set of entries:
I/am_finish_activity( 59): [1157978656,22,com.example.app/.MainActivity,app-request]
I/am_pause_activity( 59): [1157978656,com.example.app/.MainActivity]
I/am_on_paused_called(11473): com.example.app.MainActivity
I/am_destroy_activity( 59): [1157978656,22,com.example.app/.MainActivity]

I'd make a change to my auto search function. Namely, only perform the search if the user hasn't pressed a key for about 1/2 a second.
If you are typing fast, then this function is being executed several times right on top of itself, before the results are even able to come back. Meanwhile you are probably have too many cursor resources going at once causing the app to just completely fail.
update. If you consider it, typing 10 keys fairly quickly in a row could potentially mean that you have 10 different queries executing and parsing results... There could certainly be some deadlocking issues with the code that actually calls the getLotList method if it's spun multiple threads to try and update the UI. This can lead to some programs simply giving up the ghost not knowing what to do or even what thread to report the issue on.
Of course, all of that's hard to tell from the small snippet we have.

Related

Cannot parse file using JDBC

Im trying to parse a pipe delimited file and insert fields into a table. when i start the application nothing happens in my DB. My DB has 4 columns (account_name, command_name, and system_name, CreateDt). The file i am parsing has the date in the first row then extra data. The rows following i only need the first 3 fields in each the rest is extra data. the last row is the row count. i skipped the inserting date because for now but want to get back to it after at least able to insert the first 3 fields. I have little experience with parsing a file and storing data in a DB and have looked through jdbc examples to get to this point but im struggling and am sure there is a better way.
File Example
20200310|extra|extra|extra||
Mn1223|01192|windows|extra|extra|extra||
Sd1223|02390|linux|extra|extra|extra||
2
table format
account_name command_name system_name createDt
Mn1223 01192 windows 20200310
Sd1223 02390 linux 20200310
Code to parse and insert into DB
public List insertZygateData (List<ZygateEntity> parseData) throws Exception {
String filePath = "C:\\DEV\\Test_file.xlsx";
List<String> lines = Files.readAllLines(Paths.get(filePath));
// remove date and amount
lines.remove(0);
lines.remove(lines.size() - 1);
for (ZygateEntity zygateInfo : parseData){
new MapSqlParameterSource("account_name", zygateInfo.getAccountName())
.addValue("command_name", zygateInfo.getCommandName())
.addValue("system_name", zygateInfo.getSystemName())
.getValues();
}
return lines.stream()
.map(s -> s.split("[|]")).map(val -> new ZygateEntity(val[0],val[1],val[2])).collect(Collectors.toList());
}
public boolean cleantheTable() throws SQLException {
String sql = "INSERT INTO Landing.midrange_xygate_load (account_name,command_name,system_name)"+
"VALUES (:account_name,:command_name,:system_name)";
boolean truncated = false;
Statement stmt = null;
try {
String sqlTruncate = "truncate table Landing.midrange_xygate_load";
jdbcTemplate.execute(sqlTruncate);
truncated = true;
} catch (Exception e) {
e.printStackTrace();
truncated = false;
return truncated;
} finally {
if (stmt != null) {
jdbcTemplate.execute(sql);
stmt.close();
}
}
log.info("Clean the table return value :" + truncated);
return truncated;
}
}
Entity/Model
public ZygateEntity(String accountName, String commandName, String systemName){
this.accountName=accountName;
this.commandName=commandName;
this.systemName=systemName;
}
//getters and setters
#Override
public String toString() {
return "ZygateEntity [accountName=" + accountName + ", commandName=" + commandName + ", systemName=" + systemName + ", createDt=" + createDt +"]";
}
}
Taking a look at what you've provided, it seems you have a jumbled collection of bits of code, and while most of it is there, it's not all there and not quite all in the right order.
To get some kind of clarity, try to break down what it is you're doing into separate steps, and have a method that focuses on each step. In particular, you write
Im trying to parse a pipe delimited file and insert fields into a table
This naturally breaks down into two parts:
parsing the pipe-delimited file, and
inserting fields into a table.
For the first part, you seem to have most of the parts already in your insertZygateData method. In particular, this line reads all the lines of a file into a list:
List<String> lines = Files.readAllLines(Paths.get(filePath));
These lines then remove the first and last lines from the list of lines read:
// remove date and amount
lines.remove(0);
lines.remove(lines.size() - 1);
You then have some code that looks a bit out of place: this seems to be something to do with inserting into the database, but we haven't created our list of ZygateEntity objects as we haven't yet finished reading the file. Let's put this for loop to one side for the moment.
Finally, we take the list of lines we read, split them using pipes, create ZygateEntity objects from the parts and create a List of these objects, which we then return.
return lines.stream()
.map(s -> s.split("[|]")).map(val -> new ZygateEntity(val[0],val[1],val[2])).collect(Collectors.toList());
Putting this lot together, we have a useful method that parses the file, completing the first part of the task:
private List<ZygateEntity> parseZygateData() throws IOException {
String filePath = "C:\\DEV\\Test_file.xlsx";
List<String> lines = Files.readAllLines(Paths.get(filePath));
// remove date and amount
lines.remove(0);
lines.remove(lines.size() - 1);
return lines.stream()
.map(s -> s.split("[|]")).map(val -> new ZygateEntity(val[0],val[1],val[2])).collect(Collectors.toList());
}
(Of course, we could add a parameter for the file path to read, but in the interest of getting something working, it's OK to stick with the current hard-coded file path.)
So, we've got our list of ZygateEntity objects. How do we write a method to insert them into the database?
We can find a couple of the ingredients we need in your code sample. First, we need the SQL statement to insert the data. This is in your cleanThetable method:
String sql = "INSERT INTO Landing.midrange_xygate_load (account_name,command_name,system_name)"+
"VALUES (:account_name,:command_name,:system_name)";
We then have this loop:
for (ZygateEntity zygateInfo : parseData){
new MapSqlParameterSource("account_name", zygateInfo.getAccountName())
.addValue("command_name", zygateInfo.getCommandName())
.addValue("system_name", zygateInfo.getSystemName())
.getValues();
}
This loop creates a MapSqlParameterSource out of each ZygateEntity object, and then converts it to a Map<String, Object> by calling the getValues() method. But then it does nothing with this value. Effectively you're creating these objects and getting rid of them again without doing anything with them. This isn't ideal.
A MapSqlParameterSource is used with a Spring NamedParameterJdbcTemplate. Your code mentions a jdbcTemplate, which appears to be a field within the class that parses data and inserts into the database, but you don't show the full code of this class. I'm going to have to assume it's a NamedParameterJdbcTemplate rather than a 'plain' JdbcTemplate.
A NamedParameterJdbcTemplate contains a method update that takes a SQL string and a SqlParameterSource. We have a SQL string, and we're creating MapSqlParameterSource objects, so we can use these to carry out the insert. There's not a lot of point in creating one of these MapSqlParameterSource objects only to convert it to a map, so let's remove the call to getValues().
So, we now have a method to insert the data into the database:
public void insertZygateData(List<ZygateEntity> parseData) {
String sql = "INSERT INTO Landing.midrange_xygate_load (account_name,command_name,system_name)"+
"VALUES (:account_name,:command_name,:system_name)";
for (ZygateEntity zygateInfo : parseData){
SqlParameterSource source = new MapSqlParameterSource("account_name", zygateInfo.getAccountName())
.addValue("command_name", zygateInfo.getCommandName())
.addValue("system_name", zygateInfo.getSystemName());
jdbcTemplate.update(sql, source);
}
}
Finally, let's take a look at your cleanThetable method. As with the others, let's keep it focused on one task: it looks like at the moment you're trying to delete the data out of the table and then insert it in the same method, but let's have it just focus on deleting the data as we've now got a method to insert the data.
We can't immediately get rid of the String sql = ... line, because the finally block in your code uses it. If stmt is not null, then you attempt to run the INSERT statement and then close stmt.
However, stmt is never assigned any value other than null, so it remains null. stmt != null is therefore always false, so the INSERT statement never runs. Your finally block never does anything, so you would be best off removing it altogether. With your finally block gone, you can also get rid of your local variable stmt and the sql string, leaving us with a method whose focus is to truncate the table:
public boolean cleantheTable() throws SQLException {
boolean truncated = false;
try {
String sqlTruncate = "truncate table Landing.midrange_xygate_load";
jdbcTemplate.execute(sqlTruncate);
truncated = true;
} catch (Exception e) {
e.printStackTrace();
truncated = false;
return truncated;
}
log.info("Clean the table return value :" + truncated);
return truncated;
}
I'll leave it up to you to write the code that calls these methods. I wrote some code for this purpose, and it ran successfully and inserted into a database.
So, in summary, no data was being written to your database because you were never making a call to the database to insert any. In your insertZygateData method you were creating the parameter-source objects but not doing anything useful with them, and in your cleanThetable method, it looked like you were trying to insert data, but your line jdbcTemplate.execute(sql) that attempted to do this never ran. Even if stmt wasn't null, this line wouldn't work as you didn't pass the parameter values in anywhere: you would get an exception from the database as it would be expecting values for the parameters but you never gave it any.
Hopefully my explanation gives you a way of getting your code working and helps you understand why it wasn't.

Azure Document DB - Java 1.9.5 | Authorization Error

I have a collection with some documents in it. And in my application I am creating this collection first and then inserting documents. Also, based on the requirement I need to truncate (delete all documents) the collection as well. Using document db java api I have written the following code for my this purpose-
DocumentClient documentClient = getConnection(masterkey, server, portNo);
List<Database> databaseList = documentClient.queryDatabases("SELECT * FROM root r WHERE r.id='" + schemaName + "'", null).getQueryIterable().toList();
DocumentCollection collection = null;
Database databaseCache = (Database)databaseList.get(0);
List<DocumentCollection> collectionList = documentClient.queryCollections(databaseCache.getSelfLink(), "SELECT * FROM root r WHERE r.id='" + collectionName + "'", null).getQueryIterable().toList();
// truncate logic
if (collectionList.size() > 0) {
collection = ((DocumentCollection) collectionList.get(0));
if (truncate) {
try {
documentClient.deleteDocument(collection.getSelfLink(), null);
} catch (DocumentClientException e) {
e.printStackTrace();
}
}
} else { // create logic
RequestOptions requestOptions = new RequestOptions();
requestOptions.setOfferType("S1");
collection = new DocumentCollection();
collection.setId(collectionName);
try {
collection = documentClient.createCollection(databaseCache.getSelfLink(), collection, requestOptions).getResource();
} catch (DocumentClientException e) {
e.printStackTrace();
}
With the above code I am able to create a new collection successfully. Also, I am able to insert documents as well in this collection. But while truncating the collection I am getting below error-
com.microsoft.azure.documentdb.DocumentClientException: The input authorization token can't serve the request. Please check that the expected payload is built as per the protocol, and check the key being used. Server used the following payload to sign: 'delete
colls
eyckqjnw0ae=
I am using Azure Document DB Java API version 1.9.5.
It will be of great help if you can point out the error in my code or if there is any other better way of truncating collection. I would really appreciate any kind of help here.
According to your description & code, I think the issue was caused by the code below.
try {
documentClient.deleteDocument(collection.getSelfLink(), null);
} catch (DocumentClientException e) {
e.printStackTrace();
}
It seems that you want to delete a document via the code above, but pass the argument documentLink with a collection link.
So if your real intention is to delete a collection, please using the method DocumentClient.deleteCollection(collectionLink, options).

New call log record not found in android broadcastreceiver

I am working on android application that needs phone calls to be logged on the server for personal use of course. I have broadcastreceiver registered for this purpose and I am able to detect all types of calls and their details. However, it is not possible to detect accurate outgoing call time i.e. we get to detect complete OFFHOOK time for outdoing call which is not exactly call duration talked. So only for outgoing call ended case I try to read records from the call log history. I am able to read call log history from broadcastreceiver for outgoing call ended but I don't see the entry of currently received call in the call log entry. I can see all the previous calls in the call history but not the one for which I received broadcastreceiver. I am using Gabe Sechan example from here in my code. And I try to read latest call history in outgoingcallended method like this,
ContentResolver crs = globalContext.getContentResolver();
Cursor cr = getAllCallLogs(crs);
if(cr.moveToFirst()){
duration = cr.getString(cr
.getColumnIndex(android.provider.CallLog.Calls.DURATION));
callNumber = cr.getString(cr
.getColumnIndex(android.provider.CallLog.Calls.NUMBER));
}
private Cursor getAllCallLogs(ContentResolver cr) {
// reading all data in descending order according to DATE
String strOrder = android.provider.CallLog.Calls.DATE + " DESC";
Uri callUri = Uri.parse("content://call_log/calls");
Cursor cur = cr.query(callUri, null, null, null, strOrder);
return cur;
}
But the callNumber is previous call number and not the one for which I received broadcastreciver and same is the case with the duration.
I understand that by the time I try to read call log it is not updated so how do I solve this? What am I missing?
You have to add some delay before getContentResolver(), so that table get updated. You can add either Thread.sleep() or can use handler.
public void loadCursorPostDelayed(){
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
ContentResolver crs = globalContext.getContentResolver();
...
}
}, 1500);
}
}

Neo4j ExecutionEngine does not return valid results

Trying to use a similar example from the sample code found here
My sample function is:
void query()
{
String nodeResult = "";
String rows = "";
String resultString;
String columnsString;
System.out.println("In query");
// START SNIPPET: execute
ExecutionEngine engine = new ExecutionEngine( graphDb );
ExecutionResult result;
try ( Transaction ignored = graphDb.beginTx() )
{
result = engine.execute( "start n=node(*) where n.Name =~ '.*79.*' return n, n.Name" );
// END SNIPPET: execute
// START SNIPPET: items
Iterator<Node> n_column = result.columnAs( "n" );
for ( Node node : IteratorUtil.asIterable( n_column ) )
{
// note: we're grabbing the name property from the node,
// not from the n.name in this case.
nodeResult = node + ": " + node.getProperty( "Name" );
System.out.println("In for loop");
System.out.println(nodeResult);
}
// END SNIPPET: items
// START SNIPPET: columns
List<String> columns = result.columns();
// END SNIPPET: columns
// the result is now empty, get a new one
result = engine.execute( "start n=node(*) where n.Name =~ '.*79.*' return n, n.Name" );
// START SNIPPET: rows
for ( Map<String, Object> row : result )
{
for ( Entry<String, Object> column : row.entrySet() )
{
rows += column.getKey() + ": " + column.getValue() + "; ";
System.out.println("nested");
}
rows += "\n";
}
// END SNIPPET: rows
resultString = engine.execute( "start n=node(*) where n.Name =~ '.*79.*' return n.Name" ).dumpToString();
columnsString = columns.toString();
System.out.println(rows);
System.out.println(resultString);
System.out.println(columnsString);
System.out.println("leaving");
}
}
When I run this in the web console I get many results (as there are multiple nodes that have an attribute of Name that contains the pattern 79. Yet running this code returns no results. The debug print statements 'in loop' and 'nested' never print either. Thus this must mean there are not results found in the Iterator, yet that doesn't make sense.
And yes, I already checked and made sure that the graphDb variable is the same as the path for the web console. I have other code earlier that uses the same variable to write to the database.
EDIT - More info
If I place the contents of query in the same function that creates my data, I get the correct results. If I run the query by itself it returns nothing. It's almost as the query works only in the instance where I add the data and not if I come back to the database cold in a separate instance.
EDIT2 -
Here is a snippet of code that shows the bigger context of how it is being called and sharing the same DBHandle
package ContextEngine;
import ContextEngine.NeoHandle;
import java.util.LinkedList;
/*
* Class to handle streaming data from any coded source
*/
public class Streamer {
private NeoHandle myHandle;
private String contextType;
Streamer()
{
}
public void openStream(String contextType)
{
myHandle = new NeoHandle();
myHandle.createDb();
}
public void streamInput(String dataLine)
{
Context context = new Context();
/*
* get database instance
* write to database
* check for errors
* report errors & success
*/
System.out.println(dataLine);
//apply rules to data (make ContextRules do this, send type and string of data)
ContextRules contextRules = new ContextRules();
context = contextRules.processContextRules("Calls", dataLine);
//write data (using linked list from contextRules)
NeoProcessor processor = new NeoProcessor(myHandle);
processor.processContextData(context);
}
public void runQuery()
{
NeoProcessor processor = new NeoProcessor(myHandle);
processor.query();
}
public void closeStream()
{
/*
* close database instance
*/
myHandle.shutDown();
}
}
Now, if I call streamInput AND query in in the same instance (parent calls) the query returns results. If I only call query and do not enter ANY data in that instance (yet web console shows data for same query) I get nothing. Why would I have to create the Nodes and enter them into the database at runtime just to return a valid query. Shouldn't I ALWAYS get the same results with such a query?
You mention that you are using the Neo4j Browser, which comes with Neo4j. However, the example you posted is for Neo4j Embedded, which is the in-process version of Neo4j. Are you sure you are talking to the same database when you try your query in the Browser?
In order to talk to Neo4j Server from Java, I'd recommend looking at the Neo4j JDBC driver, which has good support for connecting to the Neo4j server from Java.
http://www.neo4j.org/develop/tools/jdbc
You can set up a simple connection by adding the Neo4j JDBC jar to your classpath, available here: https://github.com/neo4j-contrib/neo4j-jdbc/releases Then just use Neo4j as any JDBC driver:
Connection conn = DriverManager.getConnection("jdbc:neo4j://localhost:7474/");
ResultSet rs = conn.executeQuery("start n=node({id}) return id(n) as id", map("id", id));
while(rs.next()) {
System.out.println(rs.getLong("id"));
}
Refer to the JDBC documentation for more advanced usage.
To answer your question on why the data is not durably stored, it may be one of many reasons. I would attempt to incrementally scale back the complexity of the code to try and locate the culprit. For instance, until you've found your problem, do these one at a time:
Instead of looping through the result, print it using System.out.println(result.dumpToString());
Instead of the regex query, try just MATCH (n) RETURN n, to return all data in the database
Make sure the data you are seeing in the browser is not "old" data inserted earlier on, but really is an insert from your latest run of the Java program. You can verify this by deleting the data via the browser before running the Java program using MATCH (n) OPTIONAL MATCH (n)-[r]->() DELETE n,r;
Make sure you are actually working against the same database directories. You can verify this by leaving the server running. If you can still start your java program, unless your Java program is using the Neo4j REST Bindings, you are not using the same directory. Two Neo4j databases cannot run against the same database directory simultaneously.

Prevent continuous F5 on a web application

This is related with handling the scenario when some crazy user is holding down the F5 key to send unlimited requests to our server.
Our application is very much database and cache intensive and when such consecutive requests come in; our web application is crashing after some time. I know we need to fix the application cache handling and need to add some check at the web server but I am asked to take care of this issue in our code.
I am handling this on both Javascript and server side, but looks like still it is failing, so would like to know if you have any better solution.
My code is as follows:
Javascript Code:
function checkPageRefresh(e) {
e = e || window.event;
ar isPageRefreshed = false;
// detect if user tries to refresh
if ((e.keyCode == 116) /* F5 */ ||
(e.ctrlKey && (e.keyCode == 116)) /* Ctrl-F5 */ ||
(e.ctrlKey && (e.keyCode == 82)) /* Ctrl-R */) {
isPageRefreshed = true;
}
// only trigger special handling for page refresh
if (isPageRefreshed){
var lastRefreshTimeMillis= readCookie("last_refresh");
var currentTimeMillis = new Date().getTime();
// set cookie with now as last refresh time
createCookie(lastRefreshCookieName, currentTimeMillis);
var lastRefreshParsed = parseFloat(lastRefreshTimeMillis, 10);
var timeDiff = currentTimeMillis - lastRefreshParsed;
var F5RefreshTimeLimitMillis = <%=request.getAttribute("F5RefreshTimeLimitMillis")%>;
// if detected last refresh was within 1 second, abort refresh
if (timeDiff < F5RefreshTimeLimitMillis) {
if (e.preventDefault) {
e.preventDefault();
return;
}
}
} // end if (isPageRefreshed)
}
Java Code:
Queue<VisitsInfoHolder> recentlyVisitedUrls = (LinkedList<VisitsInfoHolder>)session.getAttribute(SupportWebKeys.RECENTLY_VISITED_URLS);
String urlBeingCalled = PageUrlUtils.getFullURL(request);
int maxCountOfRecentURLs = 3;
if(null != recentlyVisitedUrls){
//verify if last visit count is matching with the count provided
if(recentlyVisitedUrls.size() >= maxCountOfRecentURLs ) {
int noOfMatchingVisits = 0;
Long firstAccessedTime = 0l;
int count = 0;
for(VisitsInfoHolder urlIno : recentlyVisitedUrls) {
//Store the time stamp of the first record
if(count == 0 && null != urlIno) {
firstAccessedTime = urlIno.getTimeOfTheVisit();
}
count++;
//count how many visits to the current page
if(null != urlIno && null != urlIno.getUrl() && urlIno.getUrl().equalsIgnoreCase(urlBeingCalled)) {
noOfMatchingVisits++;
}
}
if (noOfMatchingVisits >= maxCountOfRecentURLs && (new Date().getTime() - firstAccessedTime) <= 1000){
LOGGER.error(">>>>> Redirecting the client to the warning page.");
VisitsInfoHolder currentVisitInfo = new VisitsInfoHolder(urlBeingCalled,new Date().getTime());
recentlyVisitedUrls.remove();
recentlyVisitedUrls.add(currentVisitInfo);
response.sendRedirect((String)request.getAttribute("F5IssueRedirectPage"));
LOGGER.error(">>>>> Redirected successfully.");
return;
}
else{
VisitsInfoHolder currentVisitInfo = new VisitsInfoHolder(urlBeingCalled,new Date().getTime());
recentlyVisitedUrls.remove();
recentlyVisitedUrls.add(currentVisitInfo);
session.setAttribute(SupportWebKeys.RECENTLY_VISITED_URLS, recentlyVisitedUrls);
}
}
else if (recentlyVisitedUrls.size() < maxCountOfRecentURLs) {
VisitsInfoHolder currentVisitInfo = new VisitsInfoHolder(urlBeingCalled,new Date().getTime());
recentlyVisitedUrls.add(currentVisitInfo);
session.setAttribute(SupportWebKeys.RECENTLY_VISITED_URLS, recentlyVisitedUrls);
}
}
else{
recentlyVisitedUrls = new LinkedList<VisitsInfoHolder>();
VisitsInfoHolder currentVisitInfo = new VisitsInfoHolder(urlBeingCalled,new Date().getTime());
recentlyVisitedUrls.add(currentVisitInfo);
session.setAttribute(SupportWebKeys.RECENTLY_VISITED_URLS, recentlyVisitedUrls);
}
Now I keep holding the F5 button then my Javascript is not understanding that the same key is held for longer time and server side code prints the following 2 loggers
Redirecting the client to the warning page.
Redirected successfully.
But in reality it is not redirecting any single time. I tried adding Thread.sleep(1000) before and after redirect, but still no luck.
Please let me know if you see any issue with my code or let me know if there is any better solution.
When you reproduce this problem are you the only person on your server? Can you reproduce this problem on your local dev instance? If so you really need to fix your server code such that it doesn't crash. You are doing something on your server that is too intensive and needs to be optimized.
Simply intercepting the F5 key on someone's browser is treating the symptoms not the disease. If you are having problems handling a single user hitting F5 really quickly it simply means you'll never be able to scale up to many simultaneous users because that's the exact same request/response pattern as a single user round tripping you with F5.
It's time to break out the profiler and check the timings on how long it takes to process a single request through the system. Then look for hotspots and optimize it. Also watch your memory usage see if you are cleaning things up or if they are growing off into infinity.

Categories

Resources