Currently I'm able to send some form data from an HTML page to a Servlet, process it, and return the result by forwarding/redirecting to a displayresults.jsp page; However I'm wondering if there's a way to process a form submission in this fashion and then return the results to the initial page? So that whatever I wish to return shows up below the form.
The idea in the end will be to have a search function up top, then have the search results appear below on the same page.
<c:choose>
<c:when test="${empty param.search}">
<form method="post"><input type="text" name="search" /></form>
</c:when>
<c:otherwise>
<%-- show search result here. --%>
</c:otherwise>
</c:choose>
Yes
Stick the results into the request object from within the servlet
Get the servlet to forward back to the request page
Add some code into the JSP to pull out the results from the request object and display them
See this for a simple example http://www.tek-tips.com/viewthread.cfm?qid=1189624&page=11
If your usecase means that you'll be jumping from the search results elsewhere and back you may wish to maintain the search results in the session.
Personally, I almost always put my "collect search criteria" and "display results" in the same servlet or JSP file. I write them with this basic structure:
if request data is present
collect search criteria from request object
check for errors
else // i.e. first time in
fill search criteria with blanks or defaults
end if
display error messages // if any, of course
display search criteria // either what we got from last cycle or defaults
if request data was present
process request
display results
end if
I like this structure because on an error, I'm set up to display the bad data, let the user fix just what was wrong, and then cycle back through. On success, I'm set to let him adjust the criteria and re-run. Everything is in one place but it's structured so it's not a mess.
When it's up to me I rarely use servlets: I prefer to use JSP for the top level and put the non-trivial, non-display code in other classes that I simply call, but that's an implementation detail. The principle works as well with servlets as with JSP.
Related
I have a JSP file in which there are two textareas and a submit button all in a form ;
<form action="" method="post">
<textarea name="inConsole" id="in" cols="100" rows="10"> </textarea> <br/>
<input type="submit" name="Send Command"/> <br/>
<textarea name="outConsole" id="out" cols="100" rows="10"></textarea>
</form>
this page is supposed to work like any SQL program. so the user types a command in the first textarea and clicks submit, then the value of textarea will be extracted to a field and a method will take care of the command and return a log (1 row inserted, error:bad syntax etc) which will be displayed in the second textarea.
I know how for example make a login page and send data and redirect user to a new page(new jsp) file if user pass is correct.
what I can't find is how can I do all the things that I said above without going to a new page while using form action.
I have checked other questions that linked the action attribute to a servlet which was confusing for me( the way that a servlet was called). I'm looking forward to use a simple scriptlet for this purpose like the one I used for my login page:
<%
DatabaseLoginTest dbLogTest = new DatabaseLoginTest();
if (dbLogTest.DBLoginChecker(request.getParameter("user"), request.getParameter("pass")) == true){
%>
<p>Login Successful</p>
<% } else { %>
<p>Login Failed</p>
<% } %>
also I'm aware that adding java scripts(not Javascript scripts:) ) to html isn't a good practice(and the reasons for it) but I think this might be easier for a simple program that I'm working on.
p.s: I'm using tomcat and Intellij for developing this web application
and I have made a custom SQL so I only need the code that gives me the textarea value and the one that sets the other one's value
Update: now I know I should use javascript but I don't know how can I send the data extracted by javascript to a java method.
If you want to do this while remaining in the same page, you have to use Javascript. This is because if you want the server to be able to re-render the page, there has to be a page refresh.
You would need to write onClick handler for the submit button and make a Ajax call to your server to a specific URL with the user input. This URL would serve the data needed for the necessary UI changes.
You can use a scriptlet to generate the HTML that would be shown in the webpage but this would only suffice for a simple use-case and it would be a lot simpler if, say, your service returned just the data required to make the UI change and actual UI change is handled by the JS.
Also,I don't think it is a bad practice to embed JS in HTML. Sure, you can optimize this by including a JS source file but that's a separate optimization.
Could you please help me in displaying message after certain work done like 1 record deleted after
deleting data from database.
In JFrame there is a method like setVisible(true), similarly is there any way in JSP?
JSP is just a HTML code generator. All you need to do is to make sure that it generates HTML the way you want. You can use JSTL core tags to control the flow of HTML code generation.
For example, assuming that you've a servlet which sets a message like follows,
request.setAttribute("message", "Record successfully deleted");
then you can conditionally display it in JSP as follows with help of JSTL <c:if>.
<c:if test="${not empty message}">
<span class="message">${message}</span>
</c:if>
See also:
Our Servlets wiki page - contains Hello World example with similar validation/messaging approach
Our JSTL wiki page - contains info how to install and use JSTL
I am creating a user authentification in JSF2, and my header displayed on every page contains this:
<c:if test="#{user.loggedIn}">
<li><h:link value="Log out" outcome="#{user.logout}"/></li>
</c:if>
User refers to the userBean, and logout() simply invalidates the session, and issues a redirect to the login page. So when the user logs in, user.loggedIn becomes true, and logout link gets displayed, but it somehow immediately gets called, and the user is immediately logged out.
Does anyone have an idea why is this happening? I thought of using h:commandLink, but it requires a form, and I'm trying to avoid it.
Edit:
I copied the wrong code... just my luck after spending an hour figuring out why the user cannot login. You can look at the previous revision to see miscopied code.
That can happen when the JSF tags are not recognized and parsed as such and it effectively get rendered as plain text wherein all EL expressions are evaluated as value expressions. It would in your case basically print the returned value of #{user.logout()}. But while EL does that, the method's logic is of course invoked.
If you remove the action attribute and open the page in browser and do a View Source, then you'll see an unparsed <h:commandLink> tag instead of the generated HTML <a> element.
Make sure that you have the h: XML namespace definied on the right URI in the root tag of the view file.
xmlns:h="http://java.sun.com/jsf/html"
Update: the <h:link> isn't intented to invoke bean actions. It's intented as a pure GET link. The outcome is per specification evaluated as a value expression, not as a method expression. The outcome must represent a view ID where the link has to navigate to. When the EL evaluates your method as a value expression, it's of course immediately invoked. Just keep using <h:commandLink> in combination with a redirect. Additional advantage is that this isn't bookmarkable nor searchbot-crawlable.
This is the example from jsfToolbox:
<h:commandLink id="link1"
value="#{bundle.checkoutLabel}"
action="#{shoppingCartBean.checkout}" />
Get rid of your parens at the end of logout.
I would like to pass a variable wordId through JSON GET to Spring-mvc Controller in my webapp. I have no problem with static url to work with json but I do not know what is best practice to do it with dynamic/parametric urls.
Controller part:
#RequestMapping(value="/delete/{wordId}", method = RequestMethod.GET)
#ResponseStatus(HttpStatus.NO_CONTENT)
public void deleteWord(#RequestParam ("wordId") Long wordId, Principal principal) {
wordService.deleteWord(wordId, principal.getName());
}
JSP part:
<c:choose>
<c:when test="${not empty accountWords}">
<c:forEach items="${accountWords}" var="word" varStatus="status">
<li class="word">
<input type="checkbox" name="word" class="word_checkbox" value="" />
<span>${word.word}</span>
<s:url value="/words/delete/${word.wordId}" var="delete_word"></s:url>
<img src="resources/gfx/delete.png" />
</li>
</c:forEach>
</c:when>
</c:choose>
jQuery part so far:
$("li.word a").click(function(e) {
e.preventDefault();
var deleteUrl = ...
$.getJSON(deleteUrl, function() {
});
});
Could you tell how should my jquery part look like to pass wordId variable to controller? I can get url from href attribute of a tag but i would like to have relative url. I'm stucked...
UPDATE:
$("#testJSON").click(function() {
$.getJSON("admin/json.html", function(w) {
$('#span_json').html("w.wordId + "<br>" + w.word);
});
});
Since the wordId is part of the URL, you should be using the #PathVariable annotation instead of #RequestParam.
Also, since you asked about best practices, I should point out that it's not a good practice to use the HTTP GET method for actions that aren't idempotent. In other words, you shouldn't use GET for actions that make a change to data on the server-side, such as deleting records from the database.
The proper HTTP method for performing a record deletion is the HTTP DELETE method. Some older browsers don't support DELETE, so you'll find a lot of code out there that does a POST for deletion instead. I don't think that's much of a problem anymore though. See http://annevankesteren.nl/2007/10/http-method-support for more detail.
Using DELETE instead of GET isn't just a good idea for the sake of "doing things the right way"... it can actually help you avoid some nasty problems. There are browser plugins that will speed-up people's experience on the web by pre-fetching all links on a page and storing them in their local cache. If a user has one of these plugins installed the plugin will "click" on every delete link on your page! Also, if you're building a public-facing application, search engine crawlers will also follow your delete links. I've seen this happen in the real world, so trust me it's a real concern!
Another RESTful best practice is to use URLs that follow the pattern of /noun/{id}, with the HTTP method serving as the verb. So, instead of /delete/{wordId} with a GET, it would be better to go with /word/{wordId} with a DELETE.
With all of my suggested changes your code would look like this:
Controller
#RequestMapping(value="/word/{wordId}", method = RequestMethod.DELETE)
#ResponseStatus(HttpStatus.NO_CONTENT)
public void deleteWord(#PathVariable ("wordId") Long wordId, Principal principal) {
wordService.deleteWord(wordId, principal.getName());
}
Unfortunately, the jQuery and JSP become a little trickier when you use DELETE instead of GET. GET is really tempting because you can just build a link, as you did like this:
<img src="resources/gfx/delete.png" />
To get the browser to use DELETE instead, you either need to have a form whose method is DELETE, or you need to invoke some JavaScript that does an Ajax DELETE. (Since you're already using Ajax, that's the technique I'll go with.) I'd start by changing your link to a button:
<button class="delete-button" id="delete_${delete_word}"><img src="resources/gfx/delete.png" /></button>
This creates a button that stores the id of the word you want to delete in the id of the button itself. Somehow you need to associate the id of a word to delete with every button, and this is one way to do it. I've seen other people put the id in a hidden span next to the button. (To be honest, I've never loved either of these techniques, and I'm hoping somebody follows up my answer with a better way to do it.)
Anyway, with that change in the body of your JSP you'll also want to add some jQuery that handles the click of all delete buttons. (Notice I put a class on the button called "delete-button" so that it would be easy to reference in jQuery.)
jQuery:
$(".delete-button").on("click", function() {
var wordId = $(this).attr("id").substring("delete_".length);
$.ajax({
type: "DELETE",
url: "/word/" + wordId,
success: function() {
// Maybe put some code here that deletes the <li> ?
}
});
});
Notice how I extracted the word id from the id attribute of the button that was clicked:
var wordId = $(this).attr("id").substring("delete_".length);
Of course you could also do it this way:
var wordId = $(this).attr("id").substring(7);
I prefer the first way of doing it because it self-documents what the substring is doing. In the second example the number 7 is a magic number that doesn't explain what's happening.
I'm trying to figure out how cookies can be used to prevent a hacker from typing in a URL to an internal part of a java web application that shouldn't be accessible unless the user is logged in.
For example, I'd like to prevent a hacker from typing in http://domain.com/myapp/listtable.jsp and be able to view the table without logging in.
I have a servlet which stores a list of all cookies it has handed out to clients. I'm struggling to understand what the JSP/JSTL code would look like to examine the cookies in the request and compare it to what the server has stored.
Something like:
<c:forEach items="${cookie}" var="currentCookie">
<!-- Compare each incoming cookie with the cookies kept in the servlet,
if there's not a match then redirect to the login page. Otherwise,
show the contents of the page below -->
</c:forEach>
<html>
--- main page HTML here
Can anyone give me some advice on how to do this?
This should be the Job of Filter not of view
Configure a Filter to check for your protected resources
Check if user's session has some value that logically makes him logged in.
if not redirect user to login view
See Also
universal-login-authorization-in-jsp
why-business-logic-should-be-moved-out-of-jsp
I would personally add my JSP or any presentation content (that you deem protected) under the WEB-INF folder and map it accordingly to your controller. That way, the servlet container will hide it from external viewing.
Even it's not the correct way to do it... in fact you can do something like that.
Try this:
<c:forEach items="${cookie}" var="currentCookie">
<!-- Compare each incoming cookie with the cookies kept in the servlet,
if there's not a match then redirect to the login page. Otherwise,
show the contents of the page below -->
${currentCookie.value.name} - ${currentCookie.value.value}<br/>
<c:if test="${currentCookie.value.name=='JSESSIONID'}">
Your Session is ${currentCookie.value.value}
</c:if>
</c:forEach>