Coexisting JSF and JSP - spring

I have a java web project in which I use JSP, now I have to use jsf because I need a functionality wich cannot be provided by jsp only. The problem that I have is that I can't cohexist the two technologies into the same project, and I cannot re-code all what I already did using the jsp technology. Can someone help me in things I should do do merge the two technologies into the same project; I'm using spring, hibernate, tiles with maven, which explain the diffoculty that I have in trying to recode all what I did ;
here is parts of my configuration files:
from my web.xml
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/spring-security.xml
/WEB-INF/applicationContext.xml
</param-value>
</context-param>
from my application-context.xml
<context:component-scan base-package="org.me.myproject" />
<mvc:annotation-driven />
<import resource="hibernate-context.xml" />
<import resource="tiles-context.xml" />
from my spring-servlet.xml
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"
p:prefix="/WEB-INF/jsp/" p:suffix=".jsp" />
if I try to change the resolver by the JSF one, it doesn't work even with jsf pages
org.springframework.web.jsf.el.SpringBeanFacesELResolver
did someone have any idea what I have to do, thank you

I get It, the solution that I made to coexist the two technologies into the same project is by redirections, in fact, I add a file which redirect from a jsp to jsf file or from a jsf to a jsf file, after the redirection, the target page (a jsf one for example) is managed by his own controller ( the managed bean in the case of jsf ).

Related

context:component-scan, why do I have to scan multiple times?

I'm trying to clear up some Spring concepts here. I have two contextConfigureLocation xml files as defined in web.xml here
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/spring-datasource.xml
/WEB-INF/security.xml
</param-value>
</context-param>
So, in the first configuraton file "spring-datasource.xml", I did a component-scan like so
<context:annotation-config />
<context:component-scan base-package="com.mycompany.root" />
my source code structure is like so
com
--->mycompany
--------------->root
--------------------->ui
--------------------->server
--------------------->etc
The issue is, my controllers decorated with #controllers under "com.mycompany.root.ui" never got picked up.
in the spring-servlet.xml, I had to do another componet-scan like so
<context:annotation-config />
<context:component-scan base-package="com.mycompany.root.ui" />
<mvc:resources mapping="/images/**" location="/images/" />
<mvc:annotation-driven />
<mvc:default-servlet-handler/>
for my controllers to get picked up.
Why is that? I thought whatever higher up in the parent configuration files should automatically be avaialbe to the children configuraton file? Or is that not the case as evident here.
[EDit] - After some reading, I think I'm more curious with controllers instantiated in the root application context, what happened to them when the spring-dispatch servlet got to them? The child applicaton context just ignored them? It will be nice if anyonne can show me some source code of dispatch servlet that did the ignore.
Thanks

Beans injected into Apache Wink with Spring aren't registered

Following on from How do I inject a Spring bean into Apache Wink?
I'm now using wink-spring-support and I thought I had things set up correctly.
web.xml includes:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath:META-INF/wink/wink-core-context.xml
classpath:applicationContext.xml
</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>restServlet</servlet-name>
<servlet-class>org.apache.wink.server.internal.servlet.RestServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>restServlet</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
META-INF/wink/wink-core-context.xml contains:
<bean class="org.apache.wink.spring.Registrar">
<property name="instances">
<set>
<ref bean="myservice" />
</set>
</property>
</bean>
<bean id="myservice" class="mystuff.ServiceImpl"/>
There's a #Autowired annotation in mystuff.ServiceImpl that injects other Spring stuff, and mystuff.ServiceImpl implements a JAX-RS annotated interface and itself includes a JAX-RS #Path("/services") annotation.
I can see Spring loading up this stuff just fine, including the myservice bean. However when I request my resources, I get a 404 not found. As Wink starts, I can see a couple of log entries that might indicate the problem:
applicationConfigLocation property was not defined
Using application classes null named in init-param applicationConfigLocation
Have I missed something somewhere? Any advice?
The problem was my misunderstanding the docs.
There is a Spring configuration META-INF/server/wink-core-context.xml provided with wink-spring-support. This registers the BeanPostProcessors that actually do the setup and must be referenced from contextConfigLocation.
I thought that I put my configuration in there, which explains why the application didn't get registered with Wink on startup.

Spring MVC, Spring Security and Hibernate cannot autowire properties between contexts

I am using Spring MVC 3.0.6 and Spring security 3.0.7. I cannot #Autowire the RoleDao class to my user class when in the security context.
my web.xml file:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/spring/root-context.xml
/WEB-INF/security-app-context.xml
</param-value>
</context-param>
<!-- Creates the Spring Container shared by all Servlets and Filters -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- Processes application requests -->
<servlet>
<servlet-name>appServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>appServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
The security-app-context.xml:
<beans:bean id="chineseCheckersEntryPoint" class="com.nike.golf.security.ChineseCheckersAuthenticationEntryPoint" />
<beans:bean id="chineseCheckersFilter" class="com.nike.golf.security.ChineseCheckersAuthenticationFilter">
<beans:property name="authenticationManager" ref="authenticationManager"/>
</beans:bean>
<http use-expressions="true" auto-config="false" entry-point-ref="chineseCheckersEntryPoint">
<intercept-url pattern="/secure/extreme/**" access="hasRole('supervisor')" />
<intercept-url pattern="/user/**" access="permitAll" />
<intercept-url pattern="/profile/**" access="isAuthenticated()" />
<intercept-url pattern="/secure/**" access="isAuthenticated()" />
<custom-filter position="PRE_AUTH_FILTER" ref="chineseCheckersFilter" />
</http>
<authentication-manager alias="authenticationManager">
<authentication-provider ref="chineseCheckersAuthenticationProvider" />
</authentication-manager>
<beans:bean id="chineseCheckersAuthenticationProvider" class="com.nike.golf.security.ChineseCheckersAuthenticationProvider" />
In my user object where it uses the roleDao, it's null. It has not been autowired. From all the research I have done online it seems to be related to the different contexts, and not being able to autowire between them.
Can someone help me understand these contexts and how I can get them into the same context?
Thank you everyone for your help. I managed to figure this out.
This question was similar to mine and got me moving in the right direction:
Declaring Spring Bean in Parent Context vs Child Context
This forum post really simplified the idea for me.
In your web.xml file you define the servlet context and the application context.
The application context is configured through these pieces of XML:
<!-- The definition of the Root Spring Container shared by all Servlets and Filters -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/spring/root-context.xml
/WEB-INF/security-app-context.xml
</param-value>
</context-param>
<!-- Creates the Spring Container shared by all Servlets and Filters -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
any number of *context.xml files you pass into the context-param > contextConfigLocation are in the application context. This is the parent context.
The servlet context gets created in the web.xml file by this bit of xml:
<servlet>
<servlet-name>appServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
The servlet context as the child context has access to the application context (parent).
This was the key thing for me to understand. So I moved all configuration I had in the servlet context, up to the application context.
Like the answer in the other question I linked to above says #Autowired still does not work. Anyone know the reason for that?
So to get around this I defined the beans and the properties in the xml all the way from the property I was concerned with down to the sessionFactory.
The thing is now I could wire up the beans I needed in xml all the way up the hierarchy to sessionFactory because it was in the same context, since I moved it up to the application context from the servlet context where it was before.
In my question I didn't even post the servlet-context.xml file because I didn't think it needed to be touched, but in fact I needed to move the configuration up to the app context if I wanted to wire things up to my security beans.
I hope that makes sense.
You can imagine a context as a set of Spring beans.
Contexts can be nested, so that the outer context can access the beans from the inner one, but not the other way around. An example for this are typical web application, the have two contexts: the inner one specified with the contextConfigLocation and loaded by ContextLoaderListener, and the outer one configured with the DispatcherServlet.
One way to merge two xml files to one context, is introducing a third apllication configuration xml file, that only include then other xml files via bean:include. And then you have only to specify this third xml files for the loader. But I am not sure if you really have 2 application contexts configured for ContextLoaderListener. -- Anyway you can try the trick with the 3. xml file.

#Secured does not work in controller, but intercept-url seems to be working fine

It doesn't look like #Secured on methods in my #Controller are being read. When security filtering based on sec:intercept-url is being used, this seems to be working just fine. The following code results in Spring Security giving me this log entry:
DEBUG: org.springframework.security.web.access.intercept.FilterSecurityInterceptor - Public object - authentication not attempted
web.xml
contextConfigLocation
/WEB-INF/spring/root-context.xml
<!-- Creates the Spring Container shared by all Servlets and Filters -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- Processes application requests -->
<servlet>
<servlet-name>appServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/spring/appServlet/servlet-context.xml
</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<!-- Filter security -->
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
servlet-context.xml holds the configuration of the viewResolvers and all the marshalling. This configuration is annotation-driven.
root-context.xml
<sec:global-method-security secured-annotations="enabled" />
<sec:http auto-config="true">
<sec:http-basic/>
</sec:http>
<!-- Declare an authentication-manager to use a custom userDetailsService -->
<sec:authentication-manager>
<sec:authentication-provider
user-service-ref="userDetailsService">
<sec:password-encoder ref="passwordEncoder" />
</sec:authentication-provider>
</sec:authentication-manager>
<bean
class="org.springframework.security.authentication.encoding.PlaintextPasswordEncoder"
id="passwordEncoder" />
<sec:user-service id="userDetailsService">
<sec:user name="john" password="john" authorities="ROLE_USER, ROLE_ADMIN" />
<sec:user name="jane" password="jane" authorities="ROLE_USER" />
</sec:user-service>
PingController.java
#Controller
public class PingController {
#Secured("ROLE_ADMIN")
#RequestMapping(value = "/ping", method = RequestMethod.GET)
public void ping() {
}
}
This doesn't seem to have any relation to which authentication method I'm using, so the basic-http-tag can be overlooked.
I have this idea that the #Secured doesn't work because of it being used in another context than the root-context.xml in which the security is being configured. I've tried to move this configuration to the servlet-context.xml, but it doesn't seem to reach the springSecurityFilterChain. Any thoughts on the problem and and my theory?
You are right, <global-method-security> is applied at per-context basis. However, you don't need to move the whole security configuration to servlet-context.xml, just add a <global-method-security> element to it.
See Spring Security FAQ (emphasis mine). If you apply pointcuts to service layer you only need to set <global-method-security> in your app's security context.
In a Spring web application, the application context which holds the
Spring MVC beans for the dispatcher servlet is often separate from the
main application context. It is often defined in a file called
myapp-servlet.xml, where “myapp” is the name assigned to the Spring
DispatcherServlet in web.xml. An application can have multiple
DispatcherServlets, each with its own isolated application context.
The beans in these “child” contexts are not visible to the rest of the
application. The “parent” application context is loaded by the
ContextLoaderListener you define in your web.xml and is visible to all
the child contexts. This parent context is usually where you define
your security configuration, including the
element). As a result any security constraints applied to methods in
these web beans will not be enforced, since the beans cannot be seen
from the DispatcherServlet context. You need to either move the
declaration to the web context or moved the
beans you want secured into the main application context.
Generally we would recommend applying method security at the service
layer rather than on individual web controllers.

#Service are constructed twice

I have a problem with my Spring application where my #Service classes are being created twice when the application starts. I know this is a problem with my configuration, as I've experienced it before, but what exactly am I doing wrong?
Is there anything fundamentally wrong with the way I've laid out my config, below? (I have omitted everything I deem to be irrelevant)
web.xml:
<servlet>
<servlet-name>myapp</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>myapp</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/myapp-config.xml
/WEB-INF/myapp-security.xml
/WEB-INF/myapp-mvc.xml
</param-value>
</context-param>
<listener>
<listener-class>com.myapp.servlet.MyAppContextListener</listener-class>
</listener>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
myapp-servlet.xml
<context:component-scan base-package="com.myapp" annotation-config="true" />
<mvc:annotation-driven />
myapp-config.xml
<context:component-scan base-package="com.myapp" annotation-config="true" />
<context:annotation-config />
In addition to #GaryF's answer, there is a following beautiful solution for this problem (used in projects generated by Spring Roo):
myapp-config.xml
<!-- Load everything except #Controllers -->
<context:component-scan base-package="com.myapp">
<context:exclude-filter expression="org.springframework.stereotype.Controller"
type="annotation"/>
</context:component-scan>
myapp-servlet.xml
<!-- Load #Controllers only -->
<context:component-scan base-package="com.myapp" use-default-filters="false">
<context:include-filter expression="org.springframework.stereotype.Controller"
type="annotation"/>
</context:component-scan>
EDIT:
Removing <context:component-scan> from myapp-config.xml means, that all your autodiscovered annotated beans are registered in DispatcherServlet's context (that is, the context loaded from myapp-servlet.xml).
However the recommended approach is to use servlet's context for presentation-specific things (such as controllers), and use the root context (myapp-config.xml) for the core services of your application. The solution above make this approach easy.
Regarding the practical considerations, when your core services are placed in servlet's application context, they can't be accessed from outside the scope of that servlet, for example, from another servlets (you may need to use another servlets to implement another access technologies) or filters (such as Spring Security filters). That's the reason for having core services in the root application context.
As an addition to the answer #axtavt gave, I’d like to give the matching Spring JavaConfig here.
In RootConfig.java:
#ComponentScan(basePackages = { "com.myapp" },
excludeFilters = #Filter({Controller.class, Configuration.class}))
In WebMvcConfig.java:
#ComponentScan(basePackages = { "com.myapp" },
useDefaultFilters = false, includeFilters = #Filter(Controller.class))
You're doing two separate component-scans over the same base-package. Remove one of them.

Resources