I am trying to use ehcache in my project.. i have specified the following properties in hibernate config file -
config.setProperty("hibernate.cache.provider_class","org.hibernate.cache.EhCacheProvider");
config.setProperty("hibernate.cache.provider_configuration_file_resource_path","ehcache.xml");
config.setProperty("hibernate.cache.use_second_level_cache","true");
config.setProperty("hibernate.cache.use_query_cache","true");
Now i am still not sure whether the results are coming from DB or the cache..
I looked around and found - Hibernate second level cache - print result where the person is suggesting HitCount/Misscount API's
However when i tried using it the hitcount and miss count is always returned 0... here's my code
String rName = "org.hibernate.cache.UpdateTimestampsCache";
Statistics stat =
HibernateHelper.getInstance().getFactory().getStatistics();
long oldMissCount =
stat.getSecondLevelCacheStatistics(rName).getMissCount();
long oldHitCount =
stat.getSecondLevelCacheStatistics(rName).getHitCount();
UserDAO user = new UserDAO();
user.read(new Long(1)); long
newMissCount =
stat.getSecondLevelCacheStatistics(rName).getMissCount();
long newHitCount =
stat.getSecondLevelCacheStatistics(rName).getHitCount();
if(oldHitCount+1 == newHitCount &&
oldMissCount+1 == newMissCount) {
System.out.println("came from DB"); }
else if(oldHitCount+1 == newHitCount
&& oldMissCount == newMissCount) {
System.out.println("came from cache");
}
Please let me know if i am using it wrong.. and what should be the rName(region Name) in this case..
Is there any other way of determining whether the second level cache is working ??
Thanks
You need to enable statistics collection:
config.setProperty("hibernate.generate_statistics", "true");
Related
I am using Couchbase Lite SDK for android and saving an object instance of MyClass as a document in the database. MyClass has an attribute that stores the date in the java.util.Date. During run time, I fetch all the instances of MyClass saved in the database and store them in the ArrayList<MyClass>. When I insert a new document into the database and read the values from the database to show all the entered instances, the date field saved in the database is retrieved as a Long when I next try to fetch the details from the database. The code I use to load the details from the database is:
Code snippet 1:
for (Field field: fields) {
field.setAccessible(true);
if (properties.containsKey(field.getName())) {
if ("date".equals(field.getName())) {
Log.d("DebugTag", properties.get(field.getName()) + "");
long dateLong = (Long) properties.get(field.getName());
details.setDate(new Date(dateLong));
} else {
field.set(details, properties.get(field.getName()));
}
} else if("_id".equals(field.getName())) {
details.set_id(document.getId());
} else {
final String msg = "Field " + field.getName() + " not present in document ";
Log.e(TAG, msg);
}
}
You can see that I have added an additional check in case the field is date. This works perfectly fine. So, I save a new entry to database and come back to the page where I see all the entries made into the database.
Now, I have implemented a new functionality to update the details of a record in the database. For updating the record I have the following implementation:
Code snippet 2:
public static boolean updateDocument(Database database, String docID, Map<String, Object> map) {
if (null == database || null == map || null == docID) {
return false;
}
boolean success = true;
Document document = database.getDocument(docID);
try {
// Have to put in the last revision id as well to update the document.
// If we do not do this, this will throw exception.
map.put("_rev", document.getProperty("_rev"));
// Putting new properties in the document ...
document.putProperties(map);
} catch (CouchbaseLiteException e) {
Log.e(TAG, "Error putting property", e);
success = false;
}
return success;
}
After doing this when I try to reload the items, it gives me exception while reading the date field in my Code snippet 1 saying that the Date object cannot be typecasted as Long and the application crashes. Now, when I again open the application, it works perfectly fine with all the changes to the edited entry reflecting correctly. Can anyone let me know the reason for this? I suspect, until we close the database connection, the changes are not committed to the actual database location and the date field in the updated entry is kept in the cache as the Date object in my case.
PS: Although, I have found a workaround for this by setting the date as a Long object in the payload (map in function updateDocument() in Code snippet 2), it would still be interesting to understand the problem I faced.
Looking at this further, this could be reasons related to auto-boxing where long to Long conversion of primitive types to the object wrapper class is crashing the application when trying to save.
Have you tried:
long value = Long.parseLong((String)...);
More specifically in Code snippet 1:
long dateLong = Long.parseLong((String)properties.get(field.getName()));
I am trying to delete an object from a list of an other object. But I'm stuck with a strange Exception. I have tryed multiple thing but here is my final test :
public static Result unpair(String tokenString)
{
Token token = Token.getToken(tokenString);
if(token == null) return ok(toJson(Error.AUTH_ERROR));
String epc = form(UnpairRequest.class).bindFromRequest().get().epc;
//Here the line throwing an Exception
CommitItem.find().where()
.eq("commit.user", token.user)
.eq("epc",epc)
.findUnique().delete();
return ok(toJson(Response.OK));
}
It raise this exception :
OptimisticLockException: Data has changed. updated [0] rows sql[delete from commit_item where epc=? and evat_price=? and ivat_price=? and vat=? and product_product_code=? and commit_id=?] bind[null]
It seems that the Lock is not released after the Select statement but I have no Idea why...
I have also try to delete my object this way :
PairingCommit commit = PairingCommit.find().where()
.eq("user", token.user).findUnique();
CommitItem item = CommitItem.find().where()
.eq("commit", commit)
.eq("epc", epc);
commit.items.remove(item);
commit.update();
But it doesn't delete my item from the database.
I don't really understand what is going wrong with my code.
EDIT: Alex Martelli Gave me a great answer which I changed only slightly in order to get working properly for me
The answer to this problem for me was
public boolean Login2(String usernamein, String passwordin) {
DatastoreService datastore = DatastoreServiceFactory
.getDatastoreService();
Filter usernamefilter = new FilterPredicate("username",
FilterOperator.EQUAL, usernamein);
Query validuserquery = new Query("Users").setFilter(usernamefilter)
.setKeysOnly();
Entity theUser = datastore.prepare(validuserquery).asSingleEntity();
if (theUser == null) {
System.out.println("Username not found");
return false;
}
return true;
}
End of EDIT
Original Post
Okay so I have spent the entire day trying to do this and have tried my best to research it but I can't do it! :(
I feel like there is probably and easy answer but I can't work it out, I feel like I have tried Everything! please please please help D:
I have a Login section of code on its own .jsp page called Index.jsp
String username = "";
String password = "";
try {
if (request.getParameter("usernamein") != null && request.getParameter("passwordin") != null) {
username = (request.getParameter("usernamein"));
password = request.getParameter("passwordin");
if(login.Login2(username, password)){
response.sendRedirect("Race.jsp");
System.out.println("go to next page");
} else {//need username/password
out.println("your username or password is incorrect");
}
}
} catch (Exception e) {
out.println("problem in getting u an p error =" + e);
}
Part way through that code is the line (login.Login2(username, password))
that code calls a method in a class using java use bean thingy
the method it calls is this:
public boolean Login2(String usernamein, String passwordin) {
DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
Filter usernamefilter = new FilterPredicate("username", FilterOperator.EQUAL, usernamein);
Query validuserquery = new Query("Users");
validuserquery.addProjection(new PropertyProjection("username", null));
System.out.println(validuserquery);
List<Entity> list = datastore.prepare(validuserquery).asList(FetchOptions.Builder.withLimit(100));
System.out.println(list);
for (Entity username : list){
System.out.println("username is equal to '"+username+"'");
if(username.equals(usernamein)){
return true;
}else
System.out.println("was not equal");
return false;
}
return false;
}
I'm trying to only go to the next page in the top code if the if statement is true, meaning that the username does exist, eventually I want it to only go to then next page if the username and password are both in the same entity i.e. the combination exists.
I hope you guys understand what i am trying to do and can help me
oh the System.out.println() for the username value outputs this:
username is equal to '<Entity [user("id")/Users(5910974510923776)]:
username = RawValue [value=[B#187c4d7]
>
'
If you need any more info just ask and i'll add it to the post :D ty
You would be best advised to query the datastore for just the username of interest...:
Query validuserquery = new Query("Users").
setFilter(new Query.FilterPredicate("username",
Query.FilterOperator.EQUAL,
usernamein)
).setKeysOnly();
Entity anyentity = datastore.prepare(validuserquery).asSingleEntity();
if(anyentity == null) {
System.out.println("was not equal");
return false;
}
return true;
This assumes there are no entities with duplicated username in your store (though you could deal with that by catching exception PreparedQuery.TooManyResultsException -- if that gets raised, it means you have more than one entity with that username, so that would be a return true case too:-).
The core idea is: getting every user entity and checking their usernames in your application code is really wasteful of resources (quite apart from the bugs in your code in this case) -- use queries to get only the relevant entity or entities, if any!-)
Try searching a bit more next time. It's not that hard, your issue was pretty easy. In any case :
Your query returns a full object, not just properties of your object. You need to do
entity.getProperty("username")
So that you see your property, not the full object.
More info here.
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.
I'm running into the following (common) error after I added a new DB table, hibernate class, and other classes to access the hibernate class:
java.lang.OutOfMemoryError: Java heap space
Here's the relevant code:
From .jsp:
<%
com.companyconnector.model.HomepageBean homepage = new com.companyconnector.model.HomepageBean();
%>
From HomepageBean:
public class HomepageBean {
...
private ReviewBean review1;
private ReviewBean review2;
private ReviewBean review3;
public HomepageBean () {
...
GetSurveyResults gsr = new GetSurveyResults();
List<ReviewBean> rbs = gsr.getRecentReviews();
review1 = rbs.get(0);
review2 = rbs.get(1);
review3 = rbs.get(2);
}
From GetSurveyResults:
public List<ReviewBean> getRecentReviews() {
List<OpenResponse> ors = DatabaseBean.getRecentReviews();
List<ReviewBean> rbs = new ArrayList<ReviewBean>();
for(int x = 0; ors.size() > x; x =+ 2) {
String employer = "";
rbs.add(new ReviewBean(ors.get(x).getUid(), employer, ors.get(x).getResponse(), ors.get(x+1).getResponse()));
}
return rbs;
}
and lastly, from DatabaseBean:
public static List<OpenResponse> getRecentReviews() {
SessionFactory session = HibernateUtil.getSessionFactory();
Session sess = session.openSession();
Transaction tx = sess.beginTransaction();
List results = sess.createQuery(
"from OpenResponse where (uid = 46) or (uid = 50) or (uid = 51)"
).list();
tx.commit();
sess.flush();
sess.close();
return results;
}
Sorry for all the code and such a long message, but I'm getting over a million instances of ReviewBean (I used jProfiler to find this). Am I doing something wrong in the for loop in GetSurveyResults? Any other problems?
I'm happy to provide more code if necessary.
Thanks for the help.
Joe
Using JProfiler to find which objects occupy the memory is a good first step. Now that you know that needlessly many instances are created, a logical next analysis step is to run your application in debug mode, and step through the code that allocates the ReviewBeans. If you do that, the bug should be obvious. (I am pretty sure I spotted it, but I'd rather teach you how to find such bugs on your own. It's a skill that is indispensable for any good programmer).
Also you probably want to close session/commit transaction if the finally block to make sure it's always invoked event if your method throws exception. Standard pattern for working with resources in java (simplified pseudo code):
Session s = null;
try {
s = openSession();
// do something useful
}
finally {
if (s != null) s.close();
}