How to get query parameters in ExceptionHandler? - exception

In our project (JBoss 7.0.2, JSF 2), we work on a solution to catch all exceptions during user navigation and redirect them to nice error pages.
I used an ExceptionHandler, inspired by a lot of examples and tutorials online.
I managed to do a redirection feature without too much difficulty: in the ExceptionHandler.handle() method, for some exceptions (expired view/session, unauthenticated user asking a denied page, ...) I redirect the user on the login page through a good old
FacesContext.getCurrentInstance().getExternalContext().redirect(myRedirectPage);
with an additional query parameter containing the original url base64 encoded, and after a successful authentication I use the same redirection mechanism to send the user back to their page.
The problem is with ViewExpiredException on JSF actions, by example when the user click after their view has expired on any button or link with action or actionListener, synchronous or ajax-style, like
<h:commandButton action="#{myBean.myAction}" value="do that" />
or
<h:commandLink value="do that too">
<f:ajax render=":aZone" execute="#form" listener="#{myBean.myOtherAction}" />
</h:commandLink>
I cannot manage to obtain the query parameters in my ExceptionHandler.handle() method.
I tried to put my parameters in a f:metadata section, like
<f:metadata>
<f:viewParam name="myParam" value="#{myBean.myParam}" />
</f:metadata>
and to include them in the action, so in the method bound to button action I returned
"myPage.xhtml?includeViewParams=true"
but it changed nothing :-/
Am I doing something wrong? Where am I supposed to find the query paremeters? Is it in
FacesContext.getCurrentInstance().getExternalContext().getRequest()
** UPDATE **
As said in comments, view params are no more available after a ViewExpiredException (quite obvious, in fact), so params are to be stored elsewhere (#BalusC quickly suggested in a request scope or through cookie).

The request parameters are available by ExternalContext#getRequestParameterMap().
Map<String, String> params = externalContext.getRequestParameterMap();
// ...
Or if your application uses same parameter name with multiple values (which is usually the case for <h:selectManyXxx> components), use ExternalContext#getRequestParameterValuesMap() instead
Map<String, String[]> params = externalContext.getRequestParameterValuesMap();
// ...
Please note that this only returns the parameters of the current request, not of the initial request in case of postbacks.
As to the ExternalContext#getRequest(), it returns in case of JSF applications running on a servlet container an instance of HttpServletRequest which you'd need to cast, but you should rarely have the need to get it. The ExternalContext, while following the Facade design pattern, has a lot of methods which are delegating to the underlying raw HTTP servlet request, session and context. You'd namely ultimately like to end up with zero javax.servlet imports in your backing beans.
Update as per your comment, you actually want to get only the view parameters which are been registered by <f:viewParam>. You can get them by ViewMetadata#getViewParameters() wherein you pass the current UIViewRoot.
Collection<UIViewParameter> viewParameters = ViewMetadata.getViewParameters(FacesContext.getCurrentInstance().getViewRoot());
// ...

Related

JMeter generates server error when trying to reproduce an autoComplete tag

I am trying to load test with JMeter.
I have a program where incidents are created.
For now, when playing the recording, it logs in fine, but when saving data it generates the following error:
SEVERE [javax.enterprise.resource.webcontainer.jsf.application] (default task-5) Error Rendering View[/alta.xhtml]: javax.el.PropertyNotFoundException: /alta.xhtml #840,111 value="#{alta.nombre}": Target Unreachable, 'null' returned null
I have noticed that maybe the error is thrown because I have auto-complete lists.
Since, an error that is also seen in the console is:
SEVERE [javax.enterprise.resource.webcontainer.jsf.application] (default task-5) Error Rendering View[/alta.xhtml]: java.lang.NullPointerException
at org.primefaces.component.autocomplete.AutoCompleteRenderer.encodeSuggestionsAsList(AutoCompleteRenderer.java:647)
How can i fix this? Apparently in the JMeter recording all the values ​​are saved...
The autocomplete of the first error that I have put is the following:
<p:autoComplete id="via"
rendered="#{not alta.isNuevoNivel}"
dropdown="true"
widgetVar="viaWV"
placeholder="Seleccione la via"
value="#{alta.nombre}"
requiredMessage="Falta la via"
completeMethod="#{alta.completeTextPrimeraVia}"
required="true"
queryDelay="100"
cache="true"
forceSelection="true"
scrollHeight="200"
minQueryLength="0"
onfocus="if (#{null eq alta.via}) {PF('viaWV').search('');};"
onclick="PF('viaWV').search('');"
autoHighlight="false"
inputStyleClass="comboEditorAutoInput"
styleClass="comboEditorAuto"
panelStyleClass="panStyleAuto"
tabindex="24"
disabled="#{alta.isObligada() or not alta.isNueva()}" >
<p:ajax event="itemSelect"
partialSubmit="true"
delay="100"
listener="#{alta.onChangeViaEdicion()}"
update="rcCampoViaModificado :formEdicionVia:via_valor"
oncomplete="rcCampoViaModificado();"
onerror="onError();"/>
<p:ajax event="clear"
immediate="true"
delay="100"
listener="#{alta.clearVialEdicion()}"
update="rcCampoViaModificado"
oncomplete="rcCampoViaModificado();"
onerror="onError();"/>
</p:autoComplete>
Most probably your request fails due to missing or improperly implemented correlation, for modern Web 2.0 applications the chance of successful replaying recorded script is close to zero as the applications heavily rely on dynamic parameters which are used for client-side state tracking or security
When you record the actions in browser JMeter saves the values which are actual at the moment, but when you try to replay the script the values are not actual anymore so you need to extract the dynamic parameters from server response (or replicate their generation logic if they cannot be extracted) and substitute hard-coded values with their dynamic counterparts.
One of the possible ways of detecting dynamic values is recording the same scenario one more time and then comparing generated JMeter test plans - all the values which differ are a subject to correlation

Passing back value from Browse-Child VM chain to caller

MVVMCross
Windows Store
Android
I have a VM that browses a hierarchy (BrowseVm) and supports forward navigation via
ShowViewModel<LeafDetailVM>
to a leaf detail ViewModel (LeafDetailVM).
When the user is on the LeafDetail View they should be able to say "I want this one" and they will be returned to the View that initiated BrowseVm.
I cannot simply Forward Navigate to the Initiator because that would leave me with an invalid back stack. I cannot have the BrowseVM view as a NoHistory page as I need it be in the back stack to support going back from the LeafDetail view.
My plan is to have the initiator start BrowseVm with a GUID. BrowseVm will pass that GUID onto LeafDetailVM.
In the "I want this one" command I will raise a Message, containing the GUID, that both BrowseVM and the initiator are subscribed to. Then I will close LeafDetailVM.
When BrowseVM receives the notification of the message it will compare the GUID and if it matches it will close itself.
When the initiator receives the notification it will deal with the now chosen data.
Does this make sense? Have I missed a much simpler way of doing this?
This is similar to How to pass a parameter from a viewmodel to its parent viewmodel but that does not deal with the back stack.
Thanks
I suggest you try stop mentally coupling how the views work on a platform to the view-models.
With the custom presenter mechanism in MvvmCross, in the app (platform specific code) you can handle navigation to a certain view-model in different ways, including closing views, modify backstack, etc.
You can interpret navigation to a view-model in whatever way you want \ need.
You can for example pass from view-model some parameters in the ShowViewModel request which the view-presenter (IMvxViewPresenter) can interpret in different ways in the Show() to display a view-model.
In your case, you can actually navigate to initiator VM passing the selected info. In the view presenter, you can modify the backstack in the way you need.
On Android, make sure you read and know about all LaunchMode flags, for example LaunchMode.SingleTask which allows you bring the initiator activity to front without creating a new one.
It's not clear to me, is BrowseVm a parent view-model to the LeafDetailVM?
More info would be needed to understand exactly your scenario.

Security in Spring MVC and JSON

I want to provide security one way or another for Sending and Getting JSON Data,but I don't know how to do this.
Our System has roles of users (System admin, General Members, etc.)
We decided send data as JSON using the Spring MVC URL pattern. I don't want everybody that outside from system to use this URL, only users can use the URL.
Example
www.example.com/services/"hereUserPass"/"hereUserName"/category/3
Each request time for different URLs, Should I control the username and password whether registered before? or What should I do for Security?
You want to implement security into your Spring Web application. You can do this at two ways:
Url Based Security
Method Based Security
Try to make another xml file as like applicationContext-security.xml Here is an example:
<http use-expressions="true">
<intercept-url pattern="/" access="permitAll"/>
<intercept-url pattern="/static/**" filters="none" />
<intercept-url pattern="/**" access="isAuthenticated()" />
<form-login />
<logout />
</http>
Here we see that permitAll means permit everybody who wants to reach that URL. filters = none has the same effect but it means that user will not go over Spring Security(Previous one goes over Spring Security but has access, filtering doesn't applied). isAuthenticated means that user can reach there if authenticated. You can also apply role based acces to urls.
Other security implementation base on middle tier security. You should add this line at your application context security file:
<global-method-security pre-post-annotations="enabled" />
so you can use method based security as like:
#PreAuthorize("hasRole('ROLE_SUPERVISOR')")
void storeVisit(Visit visit) throws DataAccessException;
You can start to reading with Spring Security implementation of Spring's Pet Clinic example: http://static.springsource.org/spring-security/site/petclinic-tutorial.html
Also I recommend you read here: http://www.mularien.com/blog/2008/07/07/5-minute-guide-to-spring-security/

In 'form action="?login"', what does the question mark mean?

Consider:
<form action="?login" method="post"> <button>Login with Google</button> </form>
I usually see the action refer to a PHP or HTML file, but the "?login" stumps me.
Background information:
This is buried within the example-google.php file from lightopenid framework. I've been staring at the OpenID code to use Google as a third-party OpenID provider for user login on my web site and the sample code all works.
I am trying to get a clearer picture of what the framework is doing when the user presses the login button. I know that we must be sending a bunch of arguments to Google on this button action, but the ?login doesn’t seem to point anywhere.
http://gitorious.org/lightopenid
A question mark denotes the query string.
It will post to the current URL with a query string parameter of login. I am not sure how you are processing the request after you click submit (post the form), but usually it would have a value assigned to it as in login=value.
It means:
http://whatever/the-current-page-url-is?login (where "login" is the query string).
It is a relative-URI notation, similar to <img src="foo.jpg"> -- note the rest of the URI was not specified explicitly.
Happy coding

Retrieving information from a web page

My application is meant to speed up the retrieval of phone call information from our telephone system.
The best way to get this information is to create a new search on the telephone system's web interface and export the results to an Excel spreadsheet which my application then imports into a DataSet.
To get the export, from the login screen, the process goes as follows:
Log in
Navigate to Reports Page
Click "Extension Detail" link
Select "Extensions" CheckBox
Select the extensions (typically all the ones currently being used) from the listbox
Specify date range
Click on Export button
It's not a big job to do it manually every day, but, for reliability, it would be great if I can make my application do this automatically the first time it starts every day.
Since more than 1 person in the company is going to use this application, having a Windows Service do it would be even better.
I don't know if it'll help, but the system is Datatex Topaz Next Generation telephone management system: http://www.datatex.co.za/downloads/index.html#TNG
Can anyone give me a basic idea how to do this?
Also, can anyone post links (in comments if need be) to pages where I can learn more about how to do this?
I have done the something similar to fetch info from a website. I cannot give you a exact answer. But the idea is to send login info to the page with form values. If the site is relying on cookies, you can use this cookie aware WebClient:
public class CookieAwareWebClient : WebClient
{
private CookieContainer cookieContainer = new CookieContainer();
protected override WebRequest GetWebRequest(Uri address)
{
WebRequest request = base.GetWebRequest(address);
if (request is HttpWebRequest)
{
(request as HttpWebRequest).CookieContainer = cookieContainer;
}
return request;
}
}
You should be aware that some sites rely on a session id being passed so the first thing I did was to fetch the session id from the page:
var client = new CookieAwareWebClient();
client.Encoding = Encoding.UTF8;
var indexHtml = client.DownloadString(*index page url*);
string sessionID = fetchSessionID(indexHtml);
Then I had to log in to the page which you can do by uploading values to the page. You can see the specific form elements with "view source" but you have to know a little HTML to do so.
var values = new NameValueCollection();
values.Add("sessionid", sessionID); //Fetched session id
values.Add("brugerid", args[0]); //Username in my case
values.Add("adgangskode", args[1]); //Password in my case
values.Add("login", "Login"); //The login button
//Logging in
client.UploadValues(*url to login*, values); //If all goes perfect, I'm logged in now
And then I could download the page I needed. In your case you may use DownloadFile(...) if the file always have the same url (something like Export.aspx?From=2010-10-10&To=2010-11-11) or UploadValues(...) where you specify the values as before but saves the result.
string html = client.DownloadString(*url*);
It seems you have a lot more steps than I did. But the principle is the same. To see what values your send to the site to login etc. you can use programs such as Fiddler (windows) which can capture the activity going on. Essential you just do exactly the same thing but watch out for session id etc. which is temporary.
The best idea is really to use some native way to fetch data, but if don't got the code, database etc. you have to do it the ugly way. You may also need a HTML parser to fetch the data (ups, you don't because you export to a file). And last but not least, keep in mind that pages can change and there is great potential to fail to login, parse etc.
Please ask for if you are uncertain what is going on.
ADDITION
The CookieAwareWebClient is not my code:
http://code.google.com/p/gardens/source/browse/Montrics/Physical.MyPyramid/CookieAwareWebClient.cs?r=26
Using CookieContainer with WebClient class
I also found some relevant threads:
What's a good tool to screen-scrape with Javascript support?
http://forums.asp.net/t/1475637.aspx
With a HTTP client, you need to do the following:
Log in, using cookies or HTTP authentication
Request a page
Submit form data
This means that you need some class or component in your program that can do HTTP, cookies, authentication and forms. With this, you do the same requests a user would do.