Faces messages not shown after replacing navigation case by implicit navigation - jsf

I removed the navigation cases from faces-config.xml and switched to implicit navigation.
FacesContext context = FacesContext.getCurrentInstance();
context.addMessage(null, new FacesMessage("Successful", "Datacenter " + ndc.componentStatsId + " is created!"));
if (result == 1)
{
return "DatacentersList.xhtml?faces-redirect=true";
}
if (result == 2)
{
return "NewDatacenter.xhtml?faces-redirect=true";
}
return null;
The navigation is working very well, but it turns out that faces messages are not displayed anymore. How is this caused and how can I fix this?

Faces messages are request scoped. They are added to the current request. A redirect instructs the browser to create a brand new GET request on given URL. That new request is not the same as the current request. That new request does not contain those faces messages at all.
You have 2 options:
Do not redirect. You was likely also not redirecting in your original navigation cases.
if (result == 1) {
return "DatacentersList.xhtml";
}
if (result == 2) {
return "NewDatacenter.xhtml";
}
Keep the messages in the flash scope. The flash scope lives effectively as long as a single redirect.
context.getExternalContext().getFlash().setKeepMessages(true);
Note that older Mojarra versions had some peculiar bugs related to this. E.g redirect to a different folder would still cause it to fail. Make sure that you're using at least Mojarra version 2.1.14 to ensure that you won't be bothered by those bugs (it's currently already at 2.1.20).

Related

How can I use Scribe with JSF to connect to the LinkedIn API?

Based upon the Scribe example on github, I'm trying to authorize my application to use LinkedIn's api.
Here is my current code that is tied to a button click:
public String generateFromLinkedIn() {
OAuthService service = new ServiceBuilder()
.provider(LinkedInApi.class)
.apiKey(apiKey)
.apiSecret(apiSecret)
.callback("http://localhost:8080/Project/faces/linkedIn.xhtml").build();
ExternalContext externalContext = FacesContext.getCurrentInstance()
.getExternalContext();
Token requestToken = service.getRequestToken();
String authUrl = service.getAuthorizationUrl(requestToken);
try {
externalContext.redirect(authUrl);
} catch (IOException ex) {
Logger.getLogger(LinkedInController.class.getName()).log(Level.SEVERE, null, ex);
}
Map<String, String> parameterMap = (Map<String, String>) externalContext.getRequestParameterMap();
Verifier v = new Verifier(parameterMap.get("oauth_verifier"));
Token accessToken = service.getAccessToken(requestToken, v);
OAuthRequest request = new OAuthRequest(Verb.GET, "https://api.linkedin.com/v1/people/~");
service.signRequest(accessToken, request);
Response response = request.send();
System.err.println(response.getBody());
return "";
}
And in my .xhtml page I have:
<h:commandButton value="Generate" action="#{linkedInController.generateFromLinkedIn()}"></h:commandButton>
Everything works okay until I try to get the Verifier from the parameter map, which does not have any oauth_verifier. I tried splitting it up into multiple methods, but so far I cannot obtain the oauth_verifier from the URL parameters even though it is clearly there after returning from LinkedIn authorization dialog.
Any suggestions on how to get this verifier correctly or how to make Scribe work with JSF?
You seem somehow to expect that the redirected request magically returns to exactly same location in the code and continues from there. This is untrue. It are effectively 2 HTTP requests. You're basically still fiddling around in the parameter map of the current request (the one which called the generateFromLinkedIn() method).
After you call redirect() you should be returning from the method. You should move the remainder of the code into the #PostConstruct or <f:viewAction> of the backing bean tied to linkedIn.xhtml. It's the one who's called with the parameter.

ServiceStack/Funq not disposing RavenDB document session after request is complete

In trying to integrate RavenDB usage with Service Stack, I ran across the following solution proposed for session management:
A: using RavenDB with ServiceStack
The proposal to use the line below to dispose of the DocumentSession object once the request is complete was an attractive one.
container.Register(c => c.Resolve<IDocumentStore>().OpenSession()).ReusedWithin(ReuseScope.Request);
From what I understand of the Funq logic, I'm registering a new DocumentSession object with the IoC container that will be resolved for IDocumentSession and will only exist for the duration of the request. That seemed like a very clean approach.
However, I have since run into the following max session requests exception from RavenDB:
The maximum number of requests (30) allowed for this session has been
reached. Raven limits the number of remote calls that a session is
allowed to make as an early warning system. Sessions are expected to
be short lived, and Raven provides facilities like Load(string[] keys)
to load multiple documents at once and batch saves.
Now, unless I'm missing something, I shouldn't be hitting a request cap on a single session if each session only exists for the duration of a single request. To get around this problem, I tried the following, quite ill-advised solution to no avail:
var session = container.Resolve<IDocumentStore>().OpenSession();
session.Advanced.MaxNumberOfRequestsPerSession = 50000;
container.Register(p => session).ReusedWithin(ReuseScope.Request);
Here is a sample of how I'm using the resolved DocumentSession instance:
private readonly IDocumentSession _session;
public UsersService(IDocumentSession session)
{
_session = session;
}
public ServiceResponse<UserProfile> Get(GetUser request)
{
var response = new ServiceResponse<UserProfile> {Successful = true};
try
{
var user = _session.Load<UserProfile>(request.UserId);
if (user == null || user.Deleted || !user.IsActive || !user.IsActive)
{
throw HttpError.NotFound("User {0} was not found.".Fmt(request.UserId));
}
response.Data = user;
}
catch (Exception ex)
{
_logger.Error(ex.Message, ex);
response.StackTrace = ex.StackTrace;
response.Errors.Add(ex.Message);
response.Successful = false;
}
return response;
}
As far as I can see, I'm implementing SS + RavenDB "by the book" as far as the integration point goes, but I'm still getting this max session request exception and I don't understand how. I also cannot reliably replicate the exception or the conditions under which it is being thrown, which is very unsettling.

Transferring from http to https in Glassfish 3.1.1

I'm using Glassfish 3.1.1 and JSF 2.0:
I have the following code:
public String doLoginOrCC() {
HttpServletRequest request = (HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest();
this.flightNumber = request.getParameter("flightNumber");
if (request.getRemoteUser() == null) {
return "login.xhtml";
} else {
return "https://" + request.getLocalAddr() + ":8181" + request.getContextPath() + "/bookSeat.xhtml";
}
}
If user is not logged in then go to login.xhtml.
If user is logged in then go to https://localhost:8181/APP/bookSeat.xhtml
Unable to find matching navigation case with from-view-id '/flightInfo.xhtml' for action '#{bookSeatController.doLoginOrCC}' with outcome 'https://127.0.0.1:8181/PlaneTicketProgram5-war/bookSeat.xhtml'
Do I have to add a Navigation Rule in my faces-config.xml file.
If so how would I write the Navigation Rule?
You cannot change the HTTP scheme by a navigation case. A navigation case does basically a forward. You need to send a HTTP redirect instead. You can use ExternalContext#redirect() for this.
ExternalContext externalContext = FacesContext.getCurrentInstance().getExternalContext();
externalContext.redirect("https://" + request.getLocalAddr() + ":8181" + request.getContextPath() + "/bookSeat.xhtml");
You only need to add a throws IOException to the bean action method.
Unrelated to the concrete problem, why aren't you logging in over HTTPS? Your problem suggests that you're logging in over HTTP which thus sends the username/password unencrypted over network. Also, grabbing the raw Servlet API from under the JSF covers should be avoided as much as possible. You can grab HTTP request parameters by ExternalContext#getRequestParameterMap() or, better, by #ManagedProperty or <f:viewParam>. You can get the remote user by ExternalContext#getRemoteUser().

Displaying results of an SPLongOperation

I am using SPLongOperation to run a lengthy operation. After completing, the gears page redirects back to the original page from which the long operation was launched. I am not able to write anything to the oriignal page using SPLongOperation.Endscript. Here is the code I am using
using (SPLongOperation operation = new SPLongOperation(this.Page))
{
//.......................
//.......................
StringBuilder endScript = new StringBuilder();
endScript.Append("document.write('Success!!');");
operation.End(Request.Url.ToString(), SPRedirectFlags.UseSource, HttpContext.Current, String.Empty, endScript.ToString());
}
You won't be able to write anything to the calling page, a new http request has been made to show you the page with the spinning wheel while your operation is under progress and then you're redirected back to the specified url (using a new request).
The easiest way to show a success message is to pass a specific querystring to your calling url by replacing your string.empty parameter with something like
operation.End(Request.Url.ToString(), SPRedirectFlags.UseSource, HttpContext.Current, "success=1");
http://msdn.microsoft.com/en-us/library/ms450341.aspx
and then on the load event, check if you have this parameter and display the relevant message (it would be better to add an item to the HttpContext.Items or doing a post instead of a get to remove the querystring but the suggested implementation will prevent you from changing your long operation call and behaviour)
Hope this will help.
Try an alert - that worked for me..
Script.Append("alert('Success!!');");
This might be of help: http://www.sharepoint-tips.com/2012/07/reporting-code-errors-when-running-code.html
SPLongOperation longOp = new SPLongOperation(this.Page);
StringBuilder sbErrors = new StringBuilder();
longOp.Begin();try
{
throw new Exception("Sample");
}
catch(Exception ex)
{
sbErrors.Append("An error occurred: " + ex.MEssage);
}
if
(sbErrors.Length > 0)
{
longOp.EndScript("document.getElementById('s4-simple-card-content').innerHTML = \"Errors have occurred during the submission. Details: " + sbErrors.ToString() + " \";");
}
//close the dialog if there were no errors
longOp.EndScript("window.frameElement.commitPopup();");

how to apply filters in jsf

I have a filter and I get Page not Found error when any client requests a JSF page in my web application. I don't know how to fix this issue.
Here is my filter code:
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse res = (HttpServletResponse) response;
HttpSession ses = req.getSession(true);
String pageRequested = req.getRequestURL().toString();
if (ses.getAttribute("userDetails") != null) {
fc.doFilter(request,response);
} else {
RequestDispatcher dis = request.getRequestDispatcher(LOGIN_PAGE);
dis.forward(request,response);
}
I have done all the necessary settings in web.xml deployment descriptor.
A 404 simply means that the requested resource is not found. Down to the point this can have 2 causes:
The URL is invalid (i.e. LOGIN_PAGE is invalid).
The resource is not there where you think it is.
To further nail down the cause in this particular problem we need to know 2 things:
What is the absolute URL of the current request? Print request.getRequestURL().
What is the absolute URL with which you can open the login page independently in webbrowser?
Then, you should be able to extract the correct LOGIN_PAGE from this information.

Resources