How to store data in field from database in Spring MVC - java

I have a problem which is related to logic than a technology, here is a scenario, (I am using Spring + Hibernate)
I need to read some data from database to return back to page on every get request, but I thought some hack here that what if using some script someone reload page very frequently, this will cause that many calls to server, for this I thought to read data and put them in global variables or class variable, by doing so i end up writing very weird code many global variable and stupid way to give them initial value like for a variable user-status which is a byte type variable I have given -2 as initial value so that my inner logic can understand no value is set for this variable from database, below is my code
#Controller
/* #Secured("hasRole('ROLE_USERS')") */
#RequestMapping("member")
public class ApplyRoles {
#Autowired
private UserInformationForAccessApplication checkUserStatus;
// we will initialize variables to avoid auto-initialize by constructor
private byte userStatus = Constant.IntializationOfGlobalVariable.GLOBALINIT,
requesttype = Constant.IntializationOfGlobalVariable.GLOBALINIT,
access = Constant.IntializationOfGlobalVariable.GLOBALINIT;
Map<String, Object> accessnrole;
Map<String, String> country;
Map<String, String> roleArray;
#Autowired
StudentEnrollmentApplication enrollmentApplication;
#Autowired
SystemProperties systemProperties;
#Autowired
EmployeeEnrollmentApplicationResume employeeEnrollmentApplicationResume;
#Autowired
AccessEnrollmentProcessing accessEnrollmentProcessing;
private String role = Constant.IntializationOfGlobalVariable.ROLENOTSET,
fname, lname;
#RequestMapping(value = "/user", method = RequestMethod.GET)
public String checkingUserStatus(Model model, HttpSession session,
Authentication authentication) {
String sessionemail = "yashprit#gmail.com";// (String) session
// .getAttribute(Constant.SessionAttributes.LOGGEDINUSER);
// first check global value, if found set than don't fetch from database
if (userStatus == Constant.IntializationOfGlobalVariable.GLOBALINIT) {
// get user status from MySQL Database
userStatus = checkUserStatus.checkStatus(sessionemail).get(0);
if (!(userStatus == Constant.UserRoleApplicationStatus.NOTAPPLIED)) {
access = checkUserStatus.checkStatus(sessionemail).get(1);
model.addAttribute(Constant.SystemName.ACCESS, access);
}
}
if (!(userStatus >= Constant.UserRoleApplicationStatus.NOTAPPLIED || userStatus <= Constant.UserRoleApplicationStatus.REJECTED)) {
model.addAttribute("error", "User status is not avaible");
return "redirect:error/pagenotfound";
} else if (userStatus == Constant.UserRoleApplicationStatus.NOTAPPLIED) {
if (requesttype == Constant.IntializationOfGlobalVariable.GLOBALINIT) {
// get request type from MongoDB database
requesttype = checkUserStatus.getRequestType(sessionemail);
}
if (!(requesttype == Constant.RequestType.NORMALEBIT || requesttype == Constant.RequestType.INVITEBIT)) {
model.addAttribute("error",
"Facing Technichal Issue, Please try again");
return "redirect:error/pagenotfound";
}
if (requesttype == Constant.RequestType.INVITEBIT) {
if (!(Byte.parseByte((String) accessnrole
.get(Constant.SystemName.ACCESS)) == Constant.Access.USERBIT)) {
accessnrole = checkUserStatus
.getAccessAndRole(sessionemail);
}
if (accessnrole.get(Constant.SystemName.ACCESS).equals(
Constant.Database.ERRORMESSAGE)
|| accessnrole.get(Constant.SystemName.ROLE).equals(
Constant.Database.ERRORMESSAGE)) {
model.addAttribute("error",
"Facing Technichal Issue, Please try again");
return "redirect:error/pagenotfound";
}
model.addAttribute(Constant.SystemName.ACCESSNROLE, accessnrole);
model.addAttribute(Constant.SystemName.REQUESTTYPE, requesttype);
}
}
model.addAttribute(Constant.SystemName.USERSTATUS, userStatus);
return "member/user";
}
}
to avoid global variable i thought of suing cookies, because I don't want to call database on every page reload in same session, once its loaded for a session than I don't have to call to database.
Anything that can help to to redesign above part of code is much appreciated
thanks

There are really 2 things that you are considering, and correctly me if I'm wrong, but:
Caching on the server (in your Java application) to avoid doing a database lookup multiple times for the same data.
Avoid the client (browser) from sending multiple requests to the server.
The first can be resolved using caching which is available in spring uses annotations on any given method. The documentation is available here.
The second is a bit more tricky and I' leave it for now unless you discover a performance problem. It's again possible to do in Spring and takes advantage of the HTTP protocol and caching controls available in the HTTP header to inform the browser how long to cache responses.

What you are thinking about is called a "cache". It is a standard Computer Science way of doing things and they have been doing research on how to use caches for as long as there have been computers.
You might want to go do some reading on the subject. I found this one by Googling "cache tutorial java" http://javalandscape.blogspot.com/2009/01/cachingcaching-algorithms-and-caching.html
In simplest terms (a one item cache) what you want is to store some data object that you recently took some time to come up with. But you also have to have some sort of identifier so you can tell if the next request is asking for the same data. If it isn't, you have to do all the work over. If it is the same data, you just return it again.
So the algorithm works something like this in this simple case:
if (storedData != null && storedRequestInfo == userRequest.requestInfo) {
return storedData;
}
storedData = youCalculateTheRequestedData();
storedRequestInfo = userRequest.requestInfo;
return storedData;
Its not any real programming language, just something to show you how it works.
The requestInfo is whatever comes in with the request that you use to look up your database stuff. You save it in storedRequestInfo after any calculation.
This shows it as returning some data to the user, that's what is in storedData.
It's a simple, one-element cache.
(To expand on this, you can store the storedRequestInfo and storedData in the session and you end up with one of these stored for each user. You can also use a java Map and store a bunch of storedData. The problem is to decide how to limit your memory use. If you store too many of these for each user, you use up too much memory. So you limit how many each user can have either by size or by count. Then you have to decide which one to delete when it gets too big. In the simple case, you always delete, in essence, the stored one and store a new one.
I noticed your comment. ECache is just a big fancy Map in the terms I used above. I don't know if it's naturally session dependent but it can be made that way by adding the session id to the cache key.)

Related

Limit a boolean to a server (Discord JDA)

How can I limit a boolean to one server?
If I use a normal boolean to create a command that can be disabled: Boolean b = true
and make it changeable with a text command:
if (event.getMessage().getContentStripped().equalsIgnoreCase("message")) {
if (event.getMember().getPermissions().contains(Permission.ADMINISTRATOR)) {
if (b) {
b = false;
event.getChannel().sendMessage("Successfully disabled the command.").queue();
} else if (!b) {
event.getChannel().sendMessage("The command is already disabled.").queue();
}
it gets disabled/enabled for all servers the bot is in. I want people to only disable it for their own server though. How can I do this?
Sry if it's easy. I haven't found anything on Google. I'm not so experienced with coding yet. I'm here to learn :)
To keep track of state per-guild you can use a map datastructure, with the guild's ID as key.
private final Map<Long, Boolean> map = new HashMap<>();
You can then store the boolean using map.put(guild.getIdLong(), false) and later load using map.get(guild.getIdLong()). Note however, that this will not persist between program restarts, since it is only stored in memory. To persist this state, you have to use a database, such as SQLite or similar.

xpages: referencing a view from a different database/application

I am very new to xpages. I have been searching the web for an answer to my question for a while now. Seems like the answer should be simple.
I have been playing around with a snippet of code that I got from Brad Balassaitis's excellent Xcellerent.net site that populates a list of "jumptoitems" for a viewpanel dynamically. The code is run from the beforeRenderResponse event of the xpage.
var viewName = getComponent('viewPanel1').getData().getViewName();
var vw = database.getView(viewName);
var colNum = 1;
var cols:Vector = vw.getColumns();
for (var i=0; i < cols.length; i++) {
if (cols[i].isSorted() && !cols[i].isHidden()) {
colNum = i + 1;
break;
}
}
var letters = #DbColumn(null, viewName, colNum);
var options = #Trim(#Unique(#UpperCase(#Left(letters, 1))))
viewScope.put('jumpToOptions', options);
It works beautifully - but I want to modify the code to reference a view in a different database. In the post Brad says that the code can be "enhanced" to accomplish this. But I have been experimenting and searching for a while and cannot accomplish the enhancement.
Thanks for any help.
--Lisa&
In your second line, you establish a handle on the view by viewName you pull from the component viewPanel1. Your call is database.getView(viewName). This amounts to a programmatic reference of NotesDatabase.getView(). If you get a handle on the other database you want to connect to, they you can invoke the same .getView() call on that handle.
First, establish your connection to the other database; this is done via the session keyword (which is a NotesSession), as such:
var extDB = session.getDatabase(dbName)
As Howard points out, that session keyword is the current user's session and will be subject to all ACL rights/assignments/roles as that user. If you need to elevate privileges to programmatically expose additional data, you can do so with the sessionAsSigner keyword (which is also a NotesSession, just with the credentials of the signer, yourself, or you can have the NSF signed as the server ID, to give it even higher privileges).
Then proceed as usual with your extDB handle in place of the database keyword (which is about the same as session.getCurrentDatabase()); like so:
var vw = extDB.getView(viewName)
The NotesDatabase.getView() call will return null if a View by that name doesn't exist in that NSF, so you'll want to ensure that it's there and programmatically check for and handle a null return.
[Edit]
Since you're using the ported # function of #DbColumn as it is, to use the approach as Frantisek Kossuth suggests may be easy, but relies on the NotesSession of the current user. To override that user's (lack of) privileges and get full visibility of all documents' values in the separate NSF, you would still need to get a handle on the columnValues for the View as shown above, using the sessionAsSigner keyword.
[/Edit]
Based on your code you need to specify database in #DbColumn formula, too.
var letters = #DbColumn([database], viewName, colNum);
You can read about it here or there...
Aside of documented formats you can use API format "server!!database" as single string value.

How to design properly the logic of getting data from DB in the case of pagination (JAVA)?

Ok, I am building an app in client and it needs to take data from DB. The app won't take all data from DB all at once but based on the pagination.
It has a simple textbox for user to enter text and a Button to search data.
Requirements:
-If the system already downloaded the data from a certain pageNo, then it won't call to server again.
-Each time it successfully called to server it needs to remember the pageNo, so that next time when user searching for that exact term it
will search for pageNo=pageNo+1 cos we searched for pageNo
already.
So here is what i did:
private HashMap<String, Integer> wordPageNoHashMap=new HashMap<String, Integer>();
button.addClickHandler(new ClickHandler(){
#Override
public void onClick(ClickEvent event) {
int pageNo=0;
if(wordPageNoHashMap.containsKey(word)){
pageNo=wordPageNoHashMap.get(word); //note: page no only increase if found result
}
else{
pageNo=1;
wordPageNoHashMap.put(word, pageNo);
}
callToDB(word,pageNo);
}
});
public void resultFromDB(ServerResult result){
int pageNo=result.getPageNo();
String word=result.getWord();
List<String> textResult=result.getResult();
if(textResult!=null && textResult.size()>0){
pageNo++;
wordPageNoHashMap.put(word, pageNo);
//show data here
}
else{
//show err here
}
}
I putting pageNo++ at the result not at the time we call.
Am i designning it ok?
or
Can u do a better design?
Assuming my understanding is correct, for a search query I will retrieve a reasonable number of records from the DB (say 500) and store it in something like a PagedListHolder and set the per page data to whatever number you want(say 20).
Now I have two options, when the user clicks next I will simply call the nextPage() and retrieve the data set. (This might be applicable for infinite loading)
Or if the user is clicks on a particular page number (conventional pagination), I will pass on the page number to the setPage() method and retrieve the elements from that page.
I have used the PagedlistHolder example to make it easy for you to understand. You may use any similiar Class if available, or you can write one.
I think this achieves your objective of not hitting the DB for the same set of data.
Let me know if it helped.

manage jsp mvc login and registration forms

I have this validate function. It validates a login form against the database.
Does java test the expressions username.isEmpty() and password.isEmpty() two times? The former in the
if ((!username.isEmpty()) && (!password.isEmpty())) , the latter in
if(username.isEmpty())
error.addError("username", "Username is mandatory.");
if(password.isEmpty())
error.addError("password", "Password is mandatory.");
?
Is there any internal mechanism which "stores" the first test's results, avoiding to redo the same tests?
I would like to keep performances and, at the same time, I have to fill the error bean.
What about if I want to put more fields with more checks, complicated with regular expressions (ex. a registration form)?
Would that function still be good?
The basic principle I want to follow is: assign true to a flag(or enter in a piece of code) ONLY if I pass all the tests. Otherwise, it will be false (by default).
Not the vice versa (a flag true by default, which could become false).
Please feel free to correct my English if it sounds bad. thanks.
public boolean validate(FormBean bean, FormErrorBean error)
{
// the validation flag
boolean valid = false;
if (bean instanceof LoginFormBean)
{
// check not null
if (!bean.isEmpty())
{
String username = ((LoginFormBean) bean).getUsername();
String password = ((LoginFormBean) bean).getPassword();
if ((!username.isEmpty()) && (!password.isEmpty()))
{
// create the DAO
UserDao uDao = new UserDao();
// check the user
valid = uDao.checkUser((LoginFormBean) bean);
// set the validation status of the bean
((LoginFormBean) bean).setValid(valid);
// add the error, if any
if (!valid)
error.addError("Either the username is not valid or the password is wrong.");
}
else
{
if(username.isEmpty())
error.addError("username", "Username is mandatory.");
if(password.isEmpty())
error.addError("password", "Password is mandatory.");
}
}
else
{
// add the empty error...
error.addError("Both the username and password are missing.");
}
}
return valid;
}
As far as I know, the test expressions will be run twice.
If you intend to run username.isEmpty() and password.isEmpty() many many times, you could first store them as booleans. This may in theory save you a tiny amount of overhead. However, given that you probably won't need that result that many times, any performance gain is negligible.
If you're adding more unique checks using regex, I can't image you needing to reuse their results. I think your code is structured just fine as it is.
Does java test the expressions username.isEmpty() and
password.isEmpty() two times?
Yes if you call the same method 2 times.
Is there any internal mechanism which "stores" the first test's
results, avoiding to redo the same tests?
You could try to store the result into two different boolean values (1 bit for each of them):
boolean isPasswordEmpty = password.isEmpty();
boolean isUsernameEmpty = username.isEmpty();
And use them into your tests.
What about if I want to put more fields with more checks, complicated
with regular expressions (ex. a registration form)? Would that
function still be good?
If you would like to push yourself forward try using Spring Web or Apache Struts for form validation and authentication methodologies.
The basic principle I want to follow is:
assign true to a flag(or enter in a piece of code) ONLY if I pass all
the tests. Otherwise, it will be false (by default). Not the vice
versa (a flag true by default, which could become false).
I think your next step will be: "Damn I need something more than a flag. I need user ID, Name and Surname...". So try using some patterns (like DTO to store what you need and transport data through application levels).
I'd like to suggest to you to pay attention to your code:
if (!bean.isEmpty()), username.isEmpty() and so on
because is NullPointerException feasable. You should ensure that your Object are not null before try accessing it.
Hope that helps,
Bye

Is it possible to use IMAP + paging?

I have a Requirement to make an IMAP client as a Web application
I achieved the functionality of Sorting as:
//userFolder is an Object of IMAPFolder
Message[] messages = userFolder.getMessages();
Arrays.sort(messages, new Comparator<Message>()
{
public int compare(Message message1, Message message2)
{
int returnValue = 0;
try
{
if (sortCriteria == SORT_SENT_DATE)
{
returnValue = message1.getSentDate().compareTo(message2.getSentDate());
}
} catch (Exception e)
{
System.out.println(e.getMessage());
e.printStackTrace();
}
if (sortType == SORT_TYPE_DESCENDING)
{
returnValue = -returnValue;
}
return returnValue;
}
});
The code snippet is not complete , its just brief
SORT_SENT_DATE,SORT_TYPE_DESCENDING are my own constants.
Actually This solution is working fine, but it fails in logic for paging
Being a Web based application, i cant expect server to load all messages for every user and sort them
(We do have situations >1000 Simultaneous users with mail boxes having > 1000 messages each )
It also does not make sense for the web server to load all, sort them, return just a small part (say 1-20),
and on the next request, again load all sort them and return (21-40). Caching possible, but whts the gaurantee user would actually make a request ?
I heard there is a class called FetchProfile, can that help me here ? (I guess it would still load all messages but just the information thats required)
Is there any other way to achieve this ?
I need a solution that could also work in Search operation (searching with paging),
I have built an archietecture to create a SearchTerm but here too i would require paging.
for ref, i have asked this same Question at :
http://www.coderanch.com/t/461408/Other-JSE-JEE-APIs/java/it-possible-use-IMAP-paging
You would need a server with the SORT extension and even that may not be enough. Then you issue SORT on the specific mailbox and FETCH only those message numbers that fall into your view.
Update based on comments:
For servers where the SORT extension is not available the next best thing is to FETCH header field representing the sort key for all items (eg. FETCH 1:* BODY[HEADER.FIELDS(SUBJECT)] for subject or FETCH 1:* BODY[HEADER.FIELDS(DATA)] for sent date), then sort based on the key. You will get a list of sorted message number this way, which should be equivalent to what the SORT command would return.
If server side cache is allowed then the best way is to keep cache of envelopes (in the IMAP ENVELOPE sense) and then update it using the techniques described in RFC 4549. It's easy to sort and page given this cache.
There are two IMAP APIs on Java - the official JavaMail API and Risoretto. Risoretto is more low-level and should allow to implement anything described above, JavaMail may be able to do so as well, but I don't have much experience with it.

Categories

Resources