Spring webflow: Continue to 'next' state from decision-state - spring

My scenario is this: I need to implement a type of authorization check to be made in multiple flows. Right now one of my flows looks like this:
<flow parent="myparent-flow">
<decision-state id="checkAuthorization">
<if test="bean.notAuthorized"
then="redirectToSomePage"
else="view1" />
</decision-state>
<view-state id="view1" />
<!-- ... -->
</flow>
I need to implement that same authorization check for a number of flows, and while I can copy-paste the same logic everywhere I would really like to, if possible, put this in the parent flow itself, which is already used to execute some logic on-start of each flow.
The problem here is the else-class in the decision-state. Since it is a parent flow to many subflows it will not know the name of the first state in the child flow. I would like to use it as such that it would somehow go ahead and execute the next state in the flow, which exists in the child flow. My optimal solution would be something like this:
<flow> <!-- flow name = myparent-flow -->
<decision-state id="checkAuthorization">
<if test="bean.notAuthorized"
then="redirectToSomeFlow"
else="continueExecutionInChildFlow" />
</decision-state>
<end-state id="redirectToSomeFlow" view="flowRedirect:someFlow" />
</flow>
This would then be defined as parent flow in all my flows so that I don't have to duplicate this logic. Is it possible to do such a thing with Spring?

One possible way to achieve it could be by setting a variable on the specific flow and use this variable for the end-state redirection afterwards, like:
<if test="bean.notAuthorized"
then="redirectToSomeFlow"
else="${conversationScope.resultView}" />
The variable could be set by using:
<set name="conversationScope.resultView" value="'viewName'" />

Related

Cocoa Scripting: "whose clause" cannot access certain properties

I am working on making my application scriptable. I struggle with the "whose" filter clause.
I want to make this work, but while name can be used, country can not:
tell application "myapp"
get every city whose name is "Berlin" -- works
get every city whose country is "Germany" -- error -1700 (Can’t make country into type specifier)
end tell
The relevant parts of the sdef look like this:
<class name="application" code="capp">
<cocoa class="NSApplication"/>
<element type="city">
<cocoa key="allCities"/>
<accessor style="index"/>
</element>
<class name="city" code="Citi" plural="cities">
<cocoa class="ScriptableCity"/>
<property name="name" code="pnam" type="text" access="r">
<cocoa key="name"/>
</property>
<property name="country" code="Ctry" type="text" access="r">
<cocoa key="country"/>
</property>
</class>
What must I do to make country work with "whose" as well? Apparently, the "whose" clause wants a type specifier, not a property name, but I can't make sense of this.
I have implemented indicesOfObjectsByEvaluatingObjectSpecifier:, but that only gets called for name, not for country.
Oh, I had it all wrong. My program code is fine. The issue is caused by the fact that I also have a class named country. So AppleScript, looking at the outmost scope for the identifier first, finds the class country and tries to use that for the comparison. Had the error message included the word "class", this would have been easier to detect, probably.
There are now two solutions:
Rename the property in the Sdef so that it does not clash with the class name any more, e.g. to country name.
Use of it in order to change the scope for the lookup of the identifier, like this:
get every city whose country of it is "Germany"
It is also important to make sure that if the same property name is used in several classes, they all use the same 4-char type code. Otherwise this problem can surface as well.

Is there a way to conditionally include attributes in custom JSP tag?

Lets say I have a field that can take 3 attributes
<myTag a="something" b="something" c="something" />
Let's say I want to only include those a,b,c attributes when a variables are not blank. So with EL it becomes something like this
<myTag a="${varA}" b="${varB}" c="${varC}" />
In the case that one or more of the variables are blank (say varB is empty) I'm getting output like:
<myTag a="a val" b c="c val" />
So b is still there, but passing a blank value.
This can cause problems with some spring <form:etc> tags if an attribute is blank (say itemLabel on form:options for example)
What if I don't want that? Is there an easy way to have the attribute not show up altogether?
I get that I can do
<c:if test="${empty b}">
<myTag a="${varA}" c="${varC}" />
</c:if>
But that means we need a giant decision tree as the number of attributes increase if each one can possibly be blank.
Does anyone know a better way to do this?

Add a message to the messageContext in the flow xml

I am implementing a forgot password process. The challenge phase would ask three previously answered questions and if they are correct it continues. However, if they are incorrect, i want to loop back to the challenge form this time with an error message stating that the answers were incorrect. Basically, I want something like this:
<view-state id="challengeForm" view="forgotPasswordChallengeView" model="challenge">
<binder>
<!-- http://stackoverflow.com/questions/10338472/debugging-spring-mvc-collection-binding -->
<binding property="questionAndAnswerList[0].answer.answer" />
<binding property="questionAndAnswerList[1].answer.answer" />
<binding property="questionAndAnswerList[2].answer.answer" />
</binder>
<on-entry>
<set name="viewScope.commandName" value="'challenge'" />
</on-entry>
<transition on="submit" bind="true" validate="true" to="checkChallenge" />
</view-state>
<action-state id="checkChallenge">
<evaluate expression="userManager.challengePasses( challange )" />
<transition on="true" to="resetPassword" />
<transition on="false" to="challengeForm">
<!-- ADD MESSAGE HERE -->
<evaluate expression="messageContext.addMessage( ... )" />
</transition>
</action-state>
...
As I see it now, i have 3 possible solutions:
Check the challenge answers in the Validator and add a message there, but this feels wrong to be doing work in the validation.
Pass the messageContext to the challengePasses method and if it fails, add the message there, but the userManager seems like it should be more like a plain service and just return a response rather than have to manage messages.
Create an new method that would be something like messageManager.addChallengeFailedMessage( messageContext ), probably the clearest separation of concerns but feels a little overboard.
So, what i am asking is: Is there a clean way to add messages to the messageContext directly in the flow XML?
I have also had this exact question in the past. What is the semantic meaning of 'validation' and what goes appropriately in the validator? I ultimately decided this type of operation should not be a part of the validator. I have used option 3 for cases similar to yours, though I agree it seems a little overboard. Option 2 isn't ideal since the method name challengePasses does not indicate that it will add error messages, and 'challengePassesAddedErrorIfNot` would be kind of ridiculous.

Get a count of a linked collection using OData and LINQ

I set up the OData feed for Stack Overflow as outlined in the wonderful article Using LINQPad to Query Stack Overflow and I want to do something like:
Users.Where(x=>x.Badges.Count==0).Take(5)
to get the users that have no Badges ("Badges? We don't need no stinkin' badges!"). I get a DataServiceQueryException:
Unfortunately, OData doesn't support aggregate functions - it supports only the limited set of querying functions described here.
Aggregate operators
All aggregate operations are unsupported against a DataServiceQuery,
including the following:
Aggregate
Average
Count
LongCount
Max
Min
Sum
Aggregate operations must either be performed on the client or be
encapsulated by a service operation.
Hopefully Microsoft will enhance the OData client in the future - it is frustrating to (seemingly) have all the power of LINQ and then not be able to use it.
Looks like Badges doesn't have a Count property. This is why the exception occurred.
<EntityType Name="Badge">
<Key>
<PropertyRef Name="Id" />
</Key>
<Property xmlns:p8="http://schemas.microsoft.com/ado/2009/02/edm/annotation" Name="Id" Type="Edm.Int32" Nullable="false" p8:StoreGeneratedPattern="Identity" />
<Property Name="UserId" Type="Edm.Int32" Nullable="true" />
<Property Name="Name" Type="Edm.String" Nullable="true" MaxLength="50" Unicode="true" FixedLength="false" />
<Property Name="Date" Type="Edm.DateTime" Nullable="true" />
<NavigationProperty Name="User" Relationship="MetaModel.BadgeUser" FromRole="Badge" ToRole="User" />
</EntityType>
Probably you'd need to process each User to check whether the Badges navigation property resolves to anything.
Filtering on count of entities in navigation properties is currently not supported (as already noted by Joe Albahari above). In the latest CTP OData supports any and all functions which would allow you to filter on "empty" navigation properties.
See
http://blogs.msdn.com/b/astoriateam/archive/2011/10/13/announcing-wcf-data-services-oct-2011-ctp-for-net-4-and-silverlight-4.aspx to get the latest CTP.
Here is a discussion of the any/all feature:
http://www.odata.org/blog/even-more-any-and-all

How to use more than one custom filter invoked after each other?

hi all i am using spring security 3.0.2
and i have one custom filter and its order is last
and i want to add another filter after that filter, is the following config right ?
<custom-filter position="LAST" ref="filter1"/>
<custom-filter after="LAST" ref="filter2"/>
After looking in my own code I noticed that I didn't use the 'ref' attribute, but instead I place this tag inside my bean definition as follow:
<bean id="ntlmFilter" class="org.springframework.security.ntlm.samples.failover.NtlmProcessingFilter">
<sec:custom-filter position="NTLM_FILTER" />
<property name="authenticationManager" ref="authenticationManager" />
<property name="retryOnAuthFailure" value="false" />
<property name="securityConfiguration" ref="securityConfiguration" />
</bean>
Source: http://github.com/aloiscochard/spring-security-ntlm-samples/blob/master/spring-security-ntlm-samples-failover/src/main/resources/applicationContext-security.xml
Even if it's for spring-security 2, the behavior is the same in version 3.
You can find all possible position in the org.springframework.security.config.http.SecurityFilters enumeration:
http://grepcode.com/file/repo1.maven.org/maven2/org.springframework.security/spring-security-config/3.0.2.RELEASE/org/springframework/security/config/http/SecurityFilters.java
You can use some postition already defined in this enumeration to define in which order your custom filters must be set.
For exemple:
one filter before LAST and one at LAST (but not after LAST ! nothing can be after LAST !)
or one filter before SWITCH_USER_FILTER and one after.
Don't know where your are placing your tags ? but I like to have them directly inside the filter bean... easier to maintain :-)
Hope that's help !
PS: Since position are based on integer you can perhaps put number instead of enumeration value (be warn to us correct position number, look at the logic inside the SecurityFilters enumeration), not sure if accepted ...

Resources