I am working on application with jsp, jstl and jsf for my college project, thats being said, I am as well very new to jsf.
Everything is going great so far. However, I seems to have a problem figuring out how to do redirect from managed bean to page with dinamyc parameters.
For example article.jsp?article_id=2
Can somebody tell me how it is done ?
I been trying to use somethinng like
FacesContext.getCurrentInstance().getExternalContext().dispatch("faces/article.jsp2?article_id=" + articleId);
But get error:
javax.servlet.ServletException: #{postComment.postClick}: javax.faces.FacesException: javax.servlet.ServletException: javax.faces.component.UIViewRoot cannot be cast to com.sun.faces.application.StateManagerImpl$TreeNode
javax.faces.webapp.FacesServlet.service(FacesServlet.java:256)
I been trying to use
response.sendRedirect("faces/article.jsp2?article_id=" + articleId);
return;
But again getting an error.
javax.servlet.ServletException: Cannot forward after response has been committed
javax.faces.webapp.FacesServlet.service(FacesServlet.java:256)
Can somebody please tell me how do i redirect from managed java bean when working with jsf ?
Bellow is my code (maybe something wrong with that and thats why redirect not working).
HttpServletRequest request = (HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest();
HttpServletResponse response = (HttpServletResponse) FacesContext.getCurrentInstance().getExternalContext().getResponse();
String articleId = request.getSession().getAttribute("article_id").toString();
//String articleId = request.getParameter("article_id");
String authorName = request.getSession().getAttribute("user_name").toString();
java.util.Calendar calendar = java.util.Calendar.getInstance();
String commentDate = String.valueOf(calendar.get(java.util.Calendar.DAY_OF_MONTH)) + ".";
commentDate += String.valueOf(calendar.get(java.util.Calendar.MONTH)) + ".";
commentDate += String.valueOf(calendar.get(java.util.Calendar.YEAR));
ArrayList error = new ArrayList();
if(commentName.contains("<"))
{
error.add("Comment name contains illegal characters");
}
if(commentBody.isEmpty() && commentBody.contains("<script"))
{
error.add("Your message body contains illegal characters");
}
if(error.size() > 0)
{
request.getSession().setAttribute("error", error);
error.clear();
FacesContext.getCurrentInstance().getExternalContext().dispatch("article.jsp2?article_id=" + articleId);
}
else
{
Comment comment = new Comment();
comment.setCommentAuthor(authorName);
comment.setCommentBody(commentBody);
comment.setCommentDate(commentDate);
comment.setCommentName(commentName);
comment.setArticleId(articleId);
DisplayArticleIO addComment = new DisplayArticleIO();
addComment.postComment(comment);
// FacesContext.getCurrentInstance().getExternalContext().dispatch("faces/article.jsp2?article_id=" + articleId);
response.sendRedirect("faces/article.jsp2?article_id=" + articleId);
return;
}
Thank you in advance.
In case some one will run into same problem.
That's what solved my problem:
FacesContext.getCurrentInstance().getExternalContext().redirect("article.jsp?article_id=" + articleId);
Why are you using dispatch in one place and redirect in the other? This isn't the source of the problem - not returning after sending responses, however, is. Other then that, if you don't mind, I have a few friendly suggestions:
You can use DateFormat to return the comment date as you want it (it will be much cleaner).
If the errors ArrayList only contains Strings, use generics (ArrayList<String>).
What are you doing with the errors?
Your sanitation of the commentName is very dangerous. You should use whitelisting instead of blacklisting - define what you wish to accept in a comment and block everything else. Right now someone could insert an <img> tag with a src pointing to a cookie stealing page which would result in a session hijack.
After changing the dispatch to a redirect add a return below it (you should always do this. Not doing this could result in what you're seeing right now, which is that you've already sent a response somewhere else, but since you haven't returned you've reached a place where you're trying to send another).
Basically, something is already sending output to the client before you make the call to response.sendRedirect(). Once something has been sent to the browser you can't redirect or forward them to a different place.
In general, any scenarios that might result in a redirect or a forward should be handled as early as possible in the request context to insure the redirect happens before you send any data to the client. Are you doing something like calling this code via a tag in the view?
FacesContext.getCurrentInstance().getExternalContext().redirect("http://www.myUrl.com");
René
Related
Think about using several filters to change response
f1 should debug the response, f2 should reformat the content and then f3 should compress it all.
I red almost all blogs about filters and the essentials from oracle, but always without success.
Problem 1: As I understand getWriter has to be called in any case to be able to write the changed response back to the original response.
This leads to the problem, that getWriter was already called -exception is thrown in the chain.
Problem 2: Is it necessary to write the response even if was not changed?
Think about a condition which let the response in the filter unchanged.
I try to show what I am doing right now in a kind of pseudo code
//VERSION 01:
doFilter(){
if (condition to change response is true){
Printwriter out = response.getWriter();
OutputStreamResponseWrapper wrappedResponse = new OutputStreamResponseWrapper(httpServletResponse);
doFilter(originalRequest,wrappedResponse);
String convertedResponse = convertResponse(wrappedResponse.getContent());
out.write(convertedResponse);
out.close(); // without this it seems not to be send to the client??
}else{
doFilter(originalRequest,originalRequest);
}
}
//VERSION 02:
doFilter(){
Printwriter out = response.getWriter();
OutputStreamResponseWrapper wrappedResponse = new OutputStreamResponseWrapper(httpServletResponse);
doFilter(originalRequest,wrappedResponse);
if (condition to change response is true){
String convertedResponse = convertResponse(wrappedResponse.getContent());
out.write(convertedResponse);
}else{
out.write(wrappedResponse.getContent());
}
out.close(); // without this it seems not to be send to the client??
}
Now call 3 of these filters after each other with different conversions. I always get the "getWriter already called"-Exception.
I don't understand, because I pass always a wrapped response-object?
Perhaps somebody has a hint what is totally wrong with my approach. Thanks a lot in advance.
I am curious as to what a better way to deal with this is, I wanted to challenge my self and see if I could break up, in a HashMap of key,value (or String, String), a string that could come back in almost any format.
the string in question is:
/user/2/update?updates=success
Thats right, a url request for a server. The issue - as we all know this could be any thing, it could come back in any form. I wanted to break it up so that it would look like:
Controller => user
action => update
params => ??? (theres a 2, a update=success ... )
Obviously The above is not a real java object.
But you get the idea.
What do you need? what have you done? what are you trying to do?
What I want to do is map this to a controller and action while passing in the parameters along the way. But i need to separate this up making sure to specify each step what is what.
What I have done is:
private Filter parseRoute(String route){
String[] parsedRoute = route.split("[?:/=]");
Filter filter = new Filter(parsedRoute);
return filter;
}
Splits on any thing that is in the url (note, : would be something like /user:id/update
so: user/2/update ... )
I then attempted to do:
public class Filter {
private HashMap<String, String> filterInfo;
public Filter(String[] filteredRoute){
if(filteredRoute.length > 0){
filterInfo.put("Controller", filteredRoute[0]);
}else{
throw new RoutingException("routes must not be empty.");
}
}
}
But this is not going to work as I expected it to...As there are too many variables at play.
including parameters before the action (those would just be used to search for that user), their could be nested routes, so multiple controller/action/controller/action ..
How would you deal with this? What would you suggest? How could you get around this? Should you just do something like:
route(controller, action, params, template); ? (template lets you render a jsp). if so how do you deal with the ?update=success
I am using HttpServer to set up the basics. But I am now lost. I am trying to keep routing as generic and "do what ever you want we will map it to the right controller, action and pass in the parameters" but I think I bit off more then I can chew.
I have looked at both spark and spring framework, and decided that the route you pass, we will map to a xml file to find the controller and action, I just need the data structure in place to do that ...
So I am looking to back up and still go with "pass me something, ill map it out."
I would probably use the URL from apache,
org.apache.tomcat.util.net.URL url = null;
try {
url = new org.apache.tomcat.util.net.URL("/user/2/update?updates=success");
// ... do some stuff with it...
} catch (Exception e) {
e.printStackTrace();
}
java.net.URI may help you.
you can get your path by getPath()
and get all of your query by getQuery(),then you can split the query by = to name value pairs.
URI uri = new URI("/user/2/update?updates=success");
// /user/2/update
System.out.println("path is " + uri.getPath());
// updates=success
System.out.println("query is " + uri.getQuery());
I am writing an application with the user of Android Java " Eclipse " + Jquery Mobile + CodeIgniter Framework
I almost finished everything but still can not proceed on the push notification issue
one big problem taken about 2 days till now from me till I have headache from such conflict :
I made the POST Request from the android and it's already sending the POST Array.
here is the php code to handle the post request...
function notification() {
if($_POST['registrationId']) {
$this->session->set_userdata('registrationId', $_POST['registrationId']);
echo 'registerationID : success'.$this->session->userdata('registrationId').'====';
}
it really echo the session userdata indeed .. but when I try to use it in any other function or pages .. it's not working ? !!! it's empty or not existed ? !!
even when I try to make the query within the function in order to store it in Database .. the session is not available like $this->session->userdata('emailid')
update 'user' set deviceid ... where emailid = $this->session->userdata('emailid')
... not working and the session is not available !!!!!
PLEASE ANYONE CAN HELP ME ? !! :(
you can ues a class to storing the post data
class PostData {
public static $registrationId = "";
}
//set data
function notification() {
if(isset($_POST['registrationId']) && empty($_POST['registrationId']) {
PostData::$registrationId = $_POST['registrationId'];
}
}
// use data
$post_registrationId = empty(PostData::$registrationId) ? PostData::$registrationId : "";
well i couldn't solve the problem through sessions .. therefore i used fopen and i have registered the registration ID in a file.txt to use it later after in the session then delete the file. hope it can help someone someday .. thank you for sharing and participating
First of all let me describe what I'm trying to do, which I'm guessing is pretty simple.
I have a website with users and want to restrict access to a view_profile.jsp page only to logged users. I have a filter mapped to:
<url-pattern>/auth/*</url-pattern>
which looks like this
try {
HttpSession session = ((HttpServletRequest)request).getSession();
UserBean user = (UserBean)session.getAttribute("currentUser");
if (user != null && user.isValid()){
System.out.println("Filter: context -> " + ((HttpServletRequest)request).getContextPath()); //returns ""
chain.doFilter(request, response);
}
else{
((HttpServletResponse)response).sendRedirect("/login.jsp"); //works fine
}
This filter is run when on the index.jsp page user will click on a link:
<a href="./auth/view_profile?profile=${sessionScope.currentUser.username}">
//yeah, he will 'view' himself - it's just an example
which is suppose to take the user to the servlet mapped to ViewProfileServlet mapped to:
<url-pattern>/auth/view_profile</url-pattern>
which looks like that:
try {
String username = (String) request.getParameter("profile");
// here is getting info from database and setting request attributes
// works fine
//response.sendRedirect("/view_profile.jsp");
System.out.println("ViewProfileServlet: In context -> " + getServletContext().getContextPath()); // returns ""
dis = getServletContext().getRequestDispatcher("/view_profile.jsp");
// i've tried request.getRequestDispatcher. no difference
System.out.println("ViewProfileServlet: forward to '/view_profile.jsp'");
dis.forward(request, response);
}
Which in turn should take the user to the /view_profile.jsp (in the root context, not in /auth) and work, which it doesn't. What happens is the ViewProfileServlet runs and the view_profile.jsp shows, although it seems that the context is still /auth because all the links on view_profile.jsp point to i.e localhost:8080/auth/some-page.jsp. Also, css files are not being loaded, they're not even requested (at least according to firebug), and page source shows 404 Glassfish Error where css's suppose to be.
I would greatly appreciate any help, it's the first time i'm even doing something in jsp and i'm completely lost here.
A forward happens entirely at server-side. The browser doesn't know about it. When it sends a request to /auth/view_profile, and receives HTML from this response, he doesn't care if the HTML has been generated by a servlet, a JSP, both, or anything else. It reads the HTML and considers it comes from the path /auth/view_profile. All the relative path in the HTML are thus relative to /auth/view_profile.
It's far easier to use absolute paths to reference images, JS and CSS paths (and even other actions, most of the time). Just make sure to use the <c:url> tag to generate the URL, so that the context path of the web-app is prepended:
<script src="<c:url value='/js/myScript.js'/>" type="text/javascript"/>
^-- the slash here makes the path absolute.
given the following controller method where username = bob and emailAddress = bob#bob.com
public static void resetPassword(String username, String emailAddress) {
String url = BASE_URL + "/users/" + username + "/reset_password";
HttpResponse response = WS.url(url).setParameter("email_address", emailAddress).get();
}
Sometimes when I make the call the url endpoing receives:
localhost:8080/api/v1/users/bob/reset_password?email_address=bob%40bob.com
then other times i get:
localhost:8080/api/v1/users/bob/reset_password?email_address=bob%2540bob.com
On the second one the # has been encoded once to %40 then the % was again encoded to %25 so you end up with %2540
If I do nothing more than wait a minute the problem goes away which makes me think it's some sort of caching problem but I can't seem to figure out what it is.
finally been recognized as a bug and has been fixed in a later release
since this does not repeduce all the times i dont know if that will help but did you try to encode the url? for example :
org.apache.commons.httpclient.util.URIUtil.encodeAll(url);
I think what is happening is when you are calling the controller the first time you send the at symbol as an at symbol.
This then gets encoded into the response and the # is converted to %40. I'm guessing when you get this back and you resend it through the browser the % in the %40 gets encoded to %25 making it %2540.
Sorry if the above is confusing, it is difficult to explain.
Simple answer would be to just do a replace on the emailAddress variable of %40 to # before passing it into WS class. There is also a urlDecode() method in the play framework which may do the trick, I've used play before but I haven't used this method.
I suspect some form of URL rewriting. Do you have an Apache Web Server running in front of your server? Maybe some RewriteRule is missing the [NE] flag.