Apply struts interceptor to subset of paths? - struts2

I'd like to apply a Struts interceptor to a subset of paths only. E.g. only requests whose path start with "/api", for example.
Seems sort of like a no-brainer but so far my google-fu is failing me badly. Can someone point me in the right direction?
Thanks!

Interceptors can be defined per-package, e.g., with a default interceptor. In your example, it would be the package with the "/api" namespace.
The other option is to configure the interceptor(s) per-action, which is irritating.

In your struts.xml, you can define a new package
<package name="yourpackage" extends="default" namespace="/api">
<default-interceptor-ref name="yourInterceptorStack"/>
</package>
In your action classes, you can specify the package as follows,
#ParentPackage("yourpackage")
public class YourAction extends ActionSupport {
...
}

Related

how to define several production environments in grails

I know you can create several custom environment for grails.
My question is i want these custom environment to be for production mode (each environment for each department with different DB and configuration).
Are there any special way to define them ? if i deploy them as is, will the war be performant or a testing war ?
Thanks
The correct way to address this is through the use of Externalized Configuration.
By doing so you will give each department the flexibility of configuring your application for their environment and you won't need to package your application for each department.
I don't have a complete solution, but I'll share what I know.
The ServletContext provides init parameters that can be set up outside of the app. The servlet container then makes them available to the app/context. The method which returns these parameters is called initParameterNames().
For example, lets say I'm running the app with Tomcat 8 and the app is called example-app. To set up some init parameters I'd create the file $CATALINA_BASE/conf/Catalina/localhost/example-app.xml
In the file, I'd save my parameters like this:
<Context>
<Parameter name="environments.production.dataSource.url" value="jdbc:h2:anotherProdDb;MVCC=TRUE;LOCK_TIMEOUT=10000;DB_CLOSE_ON_EXIT=FALSE" override="true" />
</Context>
From Grails I would be able to access this value from the ServletContext. For example, from a GSP I can read the value like this:
application.getInitParameter('environments.production.dataSource.url')
Ideally, I would merge the init parameters with the Grails config (grailsApplication.config) early in the start up process so that the init parameters override the Grails config. But I could not figure out how to it. The Grails config is accessible from GrailsAutoConfiguration (and apparently modifiable) like this:
import grails.boot.GrailsApp
import grails.boot.config.GrailsAutoConfiguration
import grails.boot.config.GrailsApplicationPostProcessor
import grails.core.GrailsApplication
class Application extends GrailsAutoConfiguration {
static void main(String[] args) {
GrailsApp.run(Application, args)
}
GrailsApplicationPostProcessor grailsApplicationPostProcessor() {
def processor = super.grailsApplicationPostProcessor()
processor.grailsApplication.config.setAt('environments.production.dataSource.url', 'testing...')
return processor
}
}
But I don't know how access the ServletContext within the grailsApplicationPostProcessor() in order to override the Grails config with init parameters.

Spring OAuth2 - custom "OAuth Approval" page at oauth/authorize

what is recommended way to create custom pages OAuth Approval page:
I have to completely override the stuff on the page, need to add styles, branding etc. What is the right way to achieve that? Where could I see the source of the default page to use it as a starting point?
I also need to override the /login page but I think the approach of overriding it is going to be pretty much the same.
The recommended way is to provide a normal Spring MVC #RequestMapping for the "/oauth/confirm_access". You can look at WhitelabelApprovalEndpoint for the default implementation. Don't forget to use #SessionAttributes("authorizationRequest") in your controller.
In addition to #DaveSyer's answer, which should work for the most of the cases. Sometimes based on configuration and customization the aforementioned method may not work, if Framew‌orkEndpointHandlerMa‌pping from Spring Security OAuth package has higher order than RequestMappingHandlerMapping of your application. If this is the case, then servlet dispatcher will never reach you mapping and will always show the default page.
One way to fix it is to change the order of mappers, given that Framew‌orkEndpointHandlerMa‌pping's order is Order.LOWEST_PRECEDENCE - 2.
Another way is to set the approval page to a custom URL, not mapped by Framew‌orkEndpointHandlerMa‌pping, thus servlet dispatcher will reaches you application's mapping
#Configuration
#EnableAuthorizationServer
protected static class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {
#Autowired
private AuthorizationEndpoint authorizationEndpoint;
#PostConstruct
public void init() {
authorizationEndpoint.setUserApprovalPage("forward:/oauth/custom_confirm_access");
authorizationEndpoint.setErrorPage("forward:/oauth/custom_error");
}
}
With such a configuration mappings of /oauth/custom_confirm_access and /oauth/custom_error will be used as a confirmation page and an error page respectively.

How to map root of Web App in Stripes to an ActionBean

I'm using DynamicMappingFilter and annotated URLs for all my actions.
I'm trying to map "/" to an existing actionBean. The actionbean I want "/" to go to, is currently bound to "/categories".
I found two ways, but I'm wondering if there is a better way in terms of performance.
I created a new IndexActionBean with #UrlBinding("/") at the top.
Inside of it, I can return a ForwardResolution to the Categories class, or I can copy paste the category class code in it, since mine is very simple.
#UrlBinding("/")
public class IndexActionBean extends AbstractActionBean {
#DefaultHandler
public ForwardResolution view() {
return new ForwardResolution(ShowCategoryActionBean.class);
}
}
It works, but I don't like having the overhead of the ForwardResolution, especially since this is the root page of the domain and will get a lot of pageviews.
I've tried to use the welcome file, but it doesn't work with DynamicMappingFilter. It's working with DispatcherServlet, such as category.action, but even then, I had problems, and only / was working, and /category and all other urls stopped working and giving 404 not found.
<welcome-file-list>
<welcome-file>category.action</welcome-file>
</welcome-file-list>
Any better ways? I cannot just rename #UrlBinding of /categories to / because I still need /categories, but I want / to forward to it as well.
In your IndexActionBean extend CategoriesBean rather than AbstractActionBean that is:
#UrlBinding("/")
public class IndexActionBean extends CategoriesBean {
}
So that you can have two url's mapped to same action bean.
Use /index.jsp to forward to your action.

How Do I Use #ConversationScoped

I am writing a JSF 2.0 application, and I want to use CDI annotations instead of the "equivalent" JSF annotations. In other words, #Model or #Named instead of #ManagedBean, and #Inject instead of #ManagedProperty.
The only thing I cannot get to work is #ViewScoped which is necessary for AJAX components. The only reliable work-around is to use #SessionScoped, which is not a good practice.
What is the correct practice? As much as I search I just get more confused.
This is on GlassFish 3.1.1, which I understand has Weld 1.1.0 in it.
UPDATE: The original form of this question said that I could not get #ConversationScoped to work. Since then I found my error and I did get it to work like so:
#Model
#ConversationScoped
public class Abean implements Serializable {
#Inject Conversation conversation;
// stuff omitted for brevity
public String getSomething() {
if (conversation.isTransient()) conversation.begin();
return "something";
}
This seems to do the trick. However now my question is changed. Where exactly are you supposed to call conversation.end()? Do I have to write a filter to detect when the user leaves the page? Or if it is left alone, just when would the Abean instance be de-referenced?
SECOND UPDATE: A very good discussion of CDI's #ConversationScoped I found here.
I am still left with the problem of how to call conversation.end(). My bean provides stateful backing to a data table browser updated via AJAX, and the optimal place to call end() is when the user navigates away from the page. However short of writing a filter to monitor the pages I don't really see any way of doing that. Any suggestion of "best practice" is welcome.
That's way simpler with the (CDI) scopes of MyFaces CODI. They have a better #ConversationScoped and you will love the #ViewAccessScoped for what you are trying.
update: JSF 2.2 (jsr 344, in early draft review) is adding an #FlowScoped CDI scope for this. More info...

URI vs Method names in Action class - Struts 2

In my Action class, I defined method names as follows:
public String doAddUser(){}
public String doDeleteUser(){}
in Struts.xml i've configured as follows:
<action name="*User" class="MyAction" method="do{1}User"></action>
From URI, if i request like AddUser or DeleteUser, its working. But i want to request like addUser or deleteUser (starts with lowercase letter). How can i acheive this?
URLs are case-sensitive, so the following will make addUser and deleteUser work, but not AddUser and DeleteUser. If you want to support both, you will need to create multiple mappings, but I don't think you should strive for that.
<action name="*User" class="MyAction" method="{1}User"></action>
public String addUser(){}
public String deleteUser(){}
Why i asked this question is, in Struts1.x, we have LookupDispatchAction concept. When user hits one url(for ex, addUser), we can call our defined method with whatever name(ie., doAddUser). In this case, we can solve my issue. But Struts 2.x, there is no possibility like that(as far as i know).
It sounds like you are looking for dynamic method invocation. Basically, if you have an action mapped as myAction, then you can invoke the addUser() method by going to myAction!addUser. myAction!execute is equivalent to the default of just myAction.

Resources