I am trying to customize the login process in Shibboleth IdP 3.0. It's basically a Spring web application, that amongst other things uses Spring flows.
I am getting the following exception (null context):
org.springframework.expression.spel.SpelEvaluationException: EL1011E:(pos 23): Method call: Attempted to call method verify(java.lang.String) on null context object
at org.springframework.expression.spel.ast.MethodReference.throwIfNotNullSafe(MethodReference.java:144)
It happens on the evaluate expression below, in this Spring web flow:
<action-state id="VerifyOtp">
<set name="flowScope.enteredOtp" value="requestParameters.j_otp"
type="java.lang.String" />
<set name="flowScope.otpSecretKey"
value="keyManager.findSecretKey(flowScope.otpUsername)"
type="ch.eifr.oshi.jaas.totp.SecretKey" />
<evaluate expression="flowScope.otpSecretKey.verify(flowScope.enteredOtp)"
result="flowScope.otpIsValid" />
<transition on="#{ flowScope.otpIsValid }" to="proceed" />
<transition on="#{ !flowScope.otpIsValid }" to="DisplayOtpPage" />
</action-state>
The flow imports the following beans:
(keyManager gets instantiated as expected)
<bean class="ch.eifr.oshi.jaas.totp.SecretKeysManagerImpl" id="keyManager" scope="singleton" />
<bean class="ch.eifr.oshi.jaas.totp.SecretKey" scope="prototype" />
I tried with and without the last line, it made no difference. I thought maybe I had to tell Spring about the classes it needs to load. That doesn't seem to be the case.
I think my problem is related to scope or dependencies, because I tried calling keyManager.toString() in a view and it returned something.
But if I call keyManager.findSecretKey('john.doe').getId() I get a null context exception. Note that the findSecretKey(String) method always returns a new key, it never returns null.
I was hoping to do it a better way, but only this worked:
<action-state id="ExtractOtpFromFormRequestAndValidate">
<set name="flashScope.enteredOtp" value="requestParameters.j_otp" type="java.lang.String"/>
<transition on="#{ keyManager.findSecretKey(flowScope.otpUsername).verify(flashScope.enteredOtp) }" to="proceed" />
<transition to="DisplayOtpPage" />
</action-state>
Related
I need to achieve viewRoot because I add a new htmlPanelGroup dynamically using DB results but always return null.
How is possible throw a evaluate expression from SWF fragment which achieve viewRoot properly?
Thanks!
Flow
<on-entry>
<set name="viewScope.code" value="requestParameters.code" />
</on-entry>
<on-render>
<evaluate expression="eventProvider.createEvent(viewScope.code)" />
</on-render>
Method
public void createEvent(String idEvent){
logger.entry("EventProvider.createEvent()");
Page p=pageBo.getDao().get(Integer.valueOf(idEvent));
pageBo.getDao().initializeElements(p);
Set<Element> elements=p.getElements();
Application app=FacesContextWrapper.getCurrentInstance().getApplication();
UIComponent parent=FacesContextWrapper.getCurrentInstance().getViewRoot().findComponent("eventContainer");
....
....
....}
Finally, I've chosen to save requestParameter in a flowScope var and so I can use it when on-render execution is invoked
<on-entry>
<set name="flowScope.code" value="requestParameters.code" />
</on-entry>
<on-render>
<evaluate expression="eventProvider.loadPage(flowScope.code)" />
</on-render>
I have a global-transition declared and I would like the value of the "validate" attribute to be conditionned or set in an action-state.
Here is how I would like to do it :
<decision-state id="decision_view">
<if test="condition == true" then="actionState1" />
</decision-state>
<action-state id="actionState1">
<evaluate result="flowScope.validateGT1" expression="true"/>
</action-state>
<global-transitions>
<transition on="gtransition1" to="gtransition1"
validate="flowScope.validateGT1" /> // Does not work, syntax error
</global-transitions>
This syntax does not work at all. Is there a way to determine the validate boolean dynamically ?
The project I am working on is using a 2.3.1 version of Spring webflow.
Thanks.
I think you cannot use the expression for boolean as it expects only literals true or false:
http://www.w3.org/TR/xmlschema-2/#boolean
Check the attirbute type for "validate" in spring webflow xsd:
xsd:attribute name="validate" type="xsd:boolean"
Instead what you can do is retrieve the boolean value in validator itself and decide if validation should be done or not as:
public class YourValidator {
public void validateStateId(YourModel model, ValidationContext context) {
RequestContext requestContext = RequestContextHolder.getRequestContext();
boolean shouldValidate = (Boolean)requestContext.getFlowScope.get("validateGT1");
if(shouldValidate){
MessageContext messages = context.getMessageContext();
...
}
}
}
Try to use evaluate
<evaluate expression="flowScope.validateGT1" result="flag" />
<global-transitions>
<transition on="gtransition1" to="gtransition1"
validate="flag" />
</global-transitions>
I'm trying to implement exception handling for my Spring 3.2.0, Spring webflow, JSF 2.1.12 application.
So far I can catch most of the exceptions using an Exception handler flow:
<persistence-context/>
<decision-state id="handleException" >
<if test="deviceManager.isMobileDevice()" then="mobileException" else="generalException"/>
</decision-state>
<view-state id="generalException" view="../views/exception/generalException.xhtml">
<on-entry>
<evaluate expression="exceptionManager.extractMessages(flowExecutionException, rootCauseException)" result="viewScope.exc"/>
</on-entry>
</view-state>
<view-state id="mobileException" view="../views/exception/mobileException.xhtml">
<on-entry>
<evaluate expression="exceptionManager.extractMessages(flowExecutionException, rootCauseException)" result="viewScope.exc"/>
</on-entry>
</view-state>
<global-transitions>
<transition on-exception="java.lang.Exception" to="handleException"/>
</global-transitions>
But this can't handle NoSuchFlowDefinitionException and similar as, if I understood well, they happens outside the flow execution.
Anyone know how to handle these exceptions?
Also I would need to map the exception to a flow and not to a static view like, for example, error.html. This because my system requires to do some extra work in the background to load the page information.
Any help will be greatly appreciated, have a good day,
Mattia
<<<<< EDIT >>>>>
I added a SimpleMappingExceptionResolver to catch the NoSuchFlowDefinitionException:
<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<property name="exceptionMappings">
<props>
<prop key="org.springframework.webflow.definition.registry.NoSuchFlowDefinitionException">
exceptionFlow
</prop>
</props>
</property>
</bean>
The Exception is catched but the resolver translate the target flow to a view, looking for a view: WEB-INF/exceptionFlow.xhtml This view does not exist as I would need to handle the exception with the flow exceptionFlow.xml
com.sun.faces.context.FacesFileNotFoundException: /WEB-INF/exceptionView.xhtml Not Found in ExternalContext as a Resource
How could I redirect that to a flow instead of a view? I tried adding a controller that maps on the view:
#Controller
#RequestMapping("/WEB-INF/exceptionFlow.xhtml")
public class ExceptionController {
#RequestMapping(method = RequestMethod.GET)
public String redirectToPublicFlowGet(ModelMap model) {
return "spring/flows/public";
}
#RequestMapping(method = RequestMethod.POST)
public String redirectToPublicFlowPost(ModelMap model) {
return "spring/flows/public";
}
}
But whatever I put on the request mapping (I tried "/WEB-INF/exceptionFlow.xhtml", "/exceptionFlow.xhtml", "exceptionFlow.xhtml". "exceptionFlow" The code never acces the methods (I put some debug breakpoint).
Anyone knows what I'm doing wrong?
Thanks have a good day
You can do it by changing
<prop key="org.springframework.webflow.definition.registry.NoSuchFlowDefinitionException">
exceptionFlow
</prop>
to
redirect:/exceptionFlow
this will create new flow execution for given flow
but you will lose information about the exception...
I have used jasig (3.5.1) cas sever and successfully configured.It works fine. my project have another requirement. I mentioned it below
i need another login mechanism. it mean rather than using stand username password, i need corporate code,mobile number and password authentication for corporate users. so i have created another Credential class for that
public class CodeMobileNumberCredintials implements Credentials{
#NotNull
#Size(min=1,message = "required.code")
private String code;
#NotNull
#Size(min=1, message = "required.mobileNumber")
private String mobileNumber;
#NotNull
#Size(min=1, message = "required.password")
private String password;
...
}
Then i created a variable called "codeMobileNumberCredintials"in web-flow.
<var name="credentials" class="org.jasig.cas.authentication.principal.UsernamePasswordCredentials" />
<var name="codeMobileNumberCredintials" class="org.jasig.cas.authentication.principal.CodeMobileNumberCredintials"/>
<view-state id="viewCorporateLoginForm" view="casCorporateLoginView" model="codeMobileNumberCredintials">
<binder>
<binding property="code" />
<binding property="mobileNumber" />
<binding property="password" />
</binder>
<on-entry>
<set name="viewScope.commandName" value="'codeMobileNumberCredintials'" />
</on-entry>
<transition on="submit" bind="true" validate="true" to="realCorporateSubmit">
<evaluate expression="authenticationViaFormAction.doCorporateBind(flowRequestContext, flowScope.codeMobileNumberCredintials)" />
</transition>
</view-state>
The issue is bean validation process not working for my custom login form.But normal username password form validated(when submiting form without givin username and password , It says "username and password blank"). But my custom autentication form not validated.It directly goes to controller class.
I have spent lot of time to do this. Can anyone help me to do my task.
Thank you
Amila
I had a similar problem. The easiest way to solve it, is to add new validator bean in
cas-servlet.xml Spring configuration file in cas-server-webapp module. In your case it will be:
<bean id="codeMobileNumberCredintialsValidator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean"
p:messageInterpolator-ref="messageInterpolator" />
There was an issue with spring web flow, resulting an error during validation. It occurs with stack trace as below and error page displayed, instead redisplaying login form:
2013-10-04 09:48:31,683 TRACE [org.jasig.cas.web.init.SafeDispatcherServlet] - <Entering method [service with arguments [[org.apache.catalina.connector.RequestFacade#411c345a, org.apache.catalina.connector.ResponseFacade#22b1221b]]>
2013-10-04 09:48:31,686 DEBUG [org.jasig.cas.web.FlowExecutionExceptionResolver] - <Ignoring the received exception due to a type mismatch> org.springframework.webflow.execution.repository.BadlyFormattedFlowExecutionKeyException: Badly formatted flow execution key '[Ljava.lang.String;#58714e00', the expected format is 'e<executionId>s<snapshotId>'
The fix is described here CAS-1142. It help me, and it summarize with adding one line <webflow:redirect-in-same-state value="false" /> to cas-servlet.xml resulting as below:
<webflow:flow-executor id="flowExecutor" flow-registry="flowRegistry">
<webflow:flow-execution-attributes>
<webflow:always-redirect-on-pause value="false"/>
<webflow:redirect-in-same-state value="false" />
</webflow:flow-execution-attributes>
<webflow:flow-execution-listeners>
<webflow:listener ref="terminateWebSessionListener" />
</webflow:flow-execution-listeners>
</webflow:flow-executor>
I am newbie to Spring Webflow, I have am using Custom FlowHandler
I can reach the respective Controller, but if set an attribute in a request Object I don't get it in JSP that is View state.
How can I proceed in this?
you shouldn't set anything to your request attributes in spring webflow - there is no need, besides webflow does some internal request redirecting and probably your attributes are los.
all the variables you create in the flow are available in view as if they were set by adding attribute to request. wether you create them via tag or create by executing some service calls via tag
<on-start>
<evaluate expression="XXXControllerwsf.firstHit(flowRequestContext)" result="flowScope.res"/>
</on-start>
<decision-state id="urlcheck">
<if test="flowScope.res.reurl== 'splash' " then="splash" else="change"/>
</decision-state>
<view-state id="change" view="${flowScope.res.reurl}">
</view-state>
<view-state id="splash" view="forward:/XXX/jsp1/XXXchange1.jsp">
<transition on="buy" to="SignInSignUp"/>
</view-state>
</flow>
Hey Miceuz thanks for Replying .....
<on-start>
<evaluate expression="XXXXControllerwsf.firstHit(flowRequestContext)" result="flowScope.res"/>
</on-start>
<decision-state id="urlcheck">
<if test="flowScope.res.reurl== 'splash' " then="splash" else="change"/>
</decision-state>
<view-state id="change" view="${flowScope.res.reurl}">
</view-state>
<view-state id="splash" view="forward:/Jahia/jsp1/XXXXchange1.jsp">
<transition on="buy" to="SignInSignUp"/>
</view-state>
</flow>
On start of the flow I am invoking a Contorller which extends FormAction
In firsthit Method I am setting a request Attribute as below
request.setAttribute("rajan", "rajanweww");
request.setAttribute("rajan", Object);
If i try to access in JSP , getting it as null... as you said Webflow has internal redirect.. Then how can I access the Value that has been set in Controller?