I;m trying to create RSS feeds for my web site. I follow the tutorial from mkyong (http://www.mkyong.com/spring-mvc/spring-3-mvc-and-rss-feed-example/) which was quite useful. According to this tutorial i create a model class and the following class
public class CustomRssViewer extends AbstractRssFeedView{
#Override
protected void buildFeedMetadata(){
//some code
}
#Override
protected List<Item> buildFeedItems(){
//some code
}
}
And finally the controller class
#Controller
public class RssController {
#RequestMapping(value="/rssfeed", method = RequestMethod.GET)
public ModelAndView getFeedInRss() {
//set the RSS content
ModelAndView mav = new ModelAndView();
mav.setViewName("rssViewer");
mav.addObject("feedContent", items);
return mav;
}
}
According to the tutorial the View rssViewer belongs the class CustomRssViewer , so i need to write it at the dispatcher servlet the following lines of code:
<bean class="org.springframework.web.servlet.view.BeanNameViewResolver" />
<bean id="rssViewer" class="com.mkyong.common.rss.CustomRssViewer" />
My problem is that i'm using apache tiles. So the rssViewer can not be recognised as i didn't enhanced it to the tiles definition. And i really don't know how can i do this. For example i need to write something as the following:
<definition name="rssViewer" template="?">
<put-attribute name="title" value=""/>
<put-attribute name="content" value=""/>
</definition>
At the template i don't know what to declare as well as at the put-attribute.Because until now at the template i use to declare the direction that a specific jsp exists. Something like this:
template="/WEB-INF/pages/mypage.jsp"
And also at the view-properties i don't know what should i declare.
Thanks in advance for any comment or response.
You should use a ContentNegotiatingViewResolver in conjuction with that example's BeanNameViewResolver. Just declare the order property of your already existing BeanNameViewResolver to be 1, and set the order property of the new ContentNegotiatingViewResolver to 0.
You should then configure the ContentNegotiatingViewResolver to use the appropriate View for RSS, and set the media type for RSS.
Here is an example from the Spring Docs:
<bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
<property name="mediaTypes">
<map>
<entry key="atom" value="application/atom+xml"/>
<entry key="html" value="text/html"/>
<entry key="json" value="application/json"/>
</map>
</property>
<property name="viewResolvers">
<list>
<bean class="org.springframework.web.servlet.view.BeanNameViewResolver"/>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>
</list>
</property>
<property name="defaultViews">
<list>
<bean class="org.springframework.web.servlet.view.json.MappingJacksonJsonView" />
</list>
</property>
</bean>
Note, they are using atom, not RSS, but the idea is the same. Also they do not set the order (which you should do).
Related
SpringMVC can't request html
I define a
#RequestMapping(value = {"/","/index"}).
I can't request index.html:
try adding "/index.html" to the #RequestMapping.
If you are trying to display the 001.html by going to /index, then make sure your 001.html is in the folder your view resolver is looking at
The value of #RequestMapping is not your view name, it's url path.
View name is defined in return.Try return index.html.
If you defined this in spring-servlet.xml:
<bean id="viewResolver"
class="org.springframework.web.servlet.view.UrlBasedViewResolver">
<property name="viewClass"
value="org.springframework.web.servlet.view.JstlView" />
<property name="prefix" value="/" />
<property name="suffix" value=".html" />
</bean>
You need return index.
I'm a newbie in spring batch and spring Mvc, and I want that a batch job (which extracts data from a database and writes it in another database) is executed from a jsp page by clicking on a button (or a link if it's possible) I'm using spring Mvc. This is my job configuration:
<bean id="jobRepository"
class="org.springframework.batch.core.repository.support.JobRepositoryFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="transactionManager" ref="transactionManager" />
<property name="databaseType" value="oracle" />
</bean>
<bean id="itemReader"
class="org.springframework.batch.item.database.JdbcCursorItemReader"
scope="step">
<property name="dataSource" ref="dataSource" />
<property name="sql"
value="select id,name,qual from users" />
<property name="rowMapper">
<bean class="tn.com.spring.UserRowMapper" />
</property>
</bean>
<bean id="oracleitemWriter"
class="org.springframework.batch.item.database.JdbcBatchItemWriter">
<property name="dataSource" ref="dataSource" />
<property name="sql">
<value>
<![CDATA[
insert into users2(id,name,qual)
values (:id,:name,:qual)
]]>
</value>
</property>
<property name="itemSqlParameterSourceProvider">
<bean
class="org.springframework.batch.item.database.BeanPropertyItemSqlParameterSourceProvider" />
</property>
</bean>
<batch:job id="Job" job-repository="jobRepository">
<batch:step id="step1">
<batch:tasklet transaction-manager="transactionManager">
<batch:chunk reader="itemReader" writer="oracleitemWriter"
commit-interval=" 10">
</batch:chunk>
</batch:tasklet>
</batch:step>
</batch:job>
<jdbc:initialize-database data-source="dataSource">
<jdbc:script
location="org/springframework/batch/core/schema-drop-oracle10g.sql" />
<jdbc:script location="org/springframework/batch/core/schema-oracle10g.sql" />
</jdbc:initialize-database>
and this is my job controller (I found it in the net but still not working!)
#Component
#Controller()
public class JobController {
#Autowired
#Qualifier("JobLauncher")
private JobLauncher jobLauncher;
#Autowired
#Qualifier("Job")
private Job job;
#RequestMapping(value = "/job")
public void job() {
try {
JobExecution execution = jobLauncher.run(job, new JobParameters());
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
and here is the button
<form action=" <%=application.getContextPath()%>/job" method="get">
<input type="submit" value="execute My job" />
</form>
Could you please help me ? Whats's missing in my configuration?
I'm confused !
Thanks in advance.
As a solution for this problem, I have made this javascript code which will invoke the execution of the job :
$(function() {
$('#JobBtn').click(function() {
$.get('${batchJobUrl}');
});
});
and in the jsp page you need to specify the Id of the button writen in the javascript code:
<input type="button" value="execute job " id='JobBtn' class="btn" />
I Hope it will help someOne..
I'm trying to achieve so that Thymeleaf can work together with Spring MVC 3 and use 2 view resolvers, one for jsp and one for html templates. I'd like my Thymeleaf ServletContextTemplateResolver to be asked first to attempt to resolve a view and if it can't find one, pass on to the Spring MVC 3 InternalResourceViewResolver.
I've set the order value of ServletContextTemplateResolver to 1 this way:
<bean id="templateResolver"
class="org.thymeleaf.templateresolver.ServletContextTemplateResolver">
<property name="prefix" value="/WEB-INF/views/" />
<property name="suffix" value=".html" />
<property name="templateMode" value="HTML5" />
<property name="order" value="1" />
<property name="cacheable" value="false" />
</bean>
and the order of InternalResourceViewResolver" to 2 in the same fashion:
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/views/" />
<property name="suffix" value=".jsp" />
<property name="order" value="2" />
</bean>
As I understand it from the docs the highest order is consulted last.
In the "views" folder I have one "index.jsp" and one "index.html" and my general idea is that first ServletContextTemplateResolver will be asked to attempt resolving and it will resolve to "index.html" if there is one, and only if no suitable view can be found by ServletContextTemplateResolver will the InternalResourceViewResolver be asked to resolve the view.
But the result I have is that when InternalResourceViewResolver is active, it resolves all views no matter what. If I comment it out then ServletContextTemplateResolver resolves fine.
Are these resolvers impossible to pair up in this fashion? What's the alternative?
Thymeleaf throws an error when trying to find pages outside of their view resolver instead of passing it onto the next view resolver. By setting the excludeViewNames, skips trying to resolve the view name within Thymeleaf. See my example code below.
/**
* Configures a {#link ThymeleafViewResolver}
*
* #return the configured {#code ThymeleafViewResolver}
*/
#Bean
public ThymeleafViewResolver thymeleafAjaxViewResolver()
{
String[] excludedViews = new String[]{
"login", "logout"};
AjaxThymeleafViewResolver resolver = new AjaxThymeleafViewResolver();
resolver.setTemplateEngine(templateEngine());
resolver.setOrder(1);
/*
* This is how we get around Thymeleaf view resolvers throwing an error instead of returning
* of null and allowing the next view resolver in the {#see
* DispatcherServlet#resolveViewName(String, Map<String, Object>, Locale,
* HttpServletRequest)} to resolve the view.
*/
resolver.setExcludedViewNames(excludedViews);
return resolver;
}
I'm using Spring 3.2 and my Spring MVC controller generate JSON data (with jackson-databind-2.2.0). I would like to customize my JSON root name with #JsonRootName (com.fasterxml.jackson.annotation.JsonRootName) annotation, however, I could not figure out how to enable it with Spring configuration.
#JsonRootName("rootNameTest")
public class MyModel {
private String prop;
public String getProp() {
return prop;
}
public void setProp(String prop) {
this.prop = prop;
}
}
Here's my settings in sevlet-context.xml
<bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
<property name="order" value="1" />
<property name="contentNegotiationManager">
<bean class="org.springframework.web.accept.ContentNegotiationManager">
<constructor-arg>
<bean class="org.springframework.web.accept.ParameterContentNegotiationStrategy">
<constructor-arg>
<map>
<entry key="json" value="application/json"/>
</map>
</constructor-arg>
</bean>
</constructor-arg>
</bean>
</property>
<property name="defaultViews">
<list>
<bean class="org.springframework.web.servlet.view.json.MappingJackson2JsonView"/>
</list>
</property>
</bean>
Please help. Thanks.
Setbelow in com.fasterxml.jackson.databind.ObjectMapper
om.configure(DeserializationFeature.UNWRAP_ROOT_VALUE, true);
om.configure(SerializationFeature.WRAP_ROOT_VALUE, true);
this may be done by extending above Class with your custom and inject in org.springframework.http.converter.json.MappingJackson2HttpMessageConverter
I am trying to enhance my spring-enabled web-app's security using Apache Shiro and am thus configuring filterchain definitions into a spring-configured file.
How do i achieve the equivalent of
#Controller
#RequestMapping("/mywebapp")
// #RequiresAuthentication (is this possible ? wish i could do this !)
public class MyWebAppController {
#RequiresRoles(value={"Role1","Role2","Role3"},logical=Logical.OR)
#RequestMapping(value="/home", method = RequestMethod.GET)
public String home() { return .. }
and my spring-config file contains this :
assume that my dispatcherservlet is mapped to /rest/*
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<property name="securityManager" ref="securityManager"/>
<property name="loginUrl" value="/rest/secure/windowslogin"/>
<property name="successUrl" value="/mywebapp/rest/menu"/>
<property name="unauthorizedUrl" value="/mywebapp/rest/unauthorized"/>
<property name="filters">
<util:map>
<entry key="anon">
<bean class="org.apache.shiro.web.filter.authc.AnonymousFilter"/>
</entry>
<entry key="authc">
<!-- why is this not invoked ? -->
<bean class="org.apache.shiro.web.filter.authc.PassThruAuthenticationFilter">
</bean>
</entry>
<entry key="roles">
<bean class="org.apache.shiro.web.filter.authz.RolesAuthorizationFilter"/>
</entry>
</util:map>
</property>
<property name="filterChainDefinitions">
<value>
/rest/secure/** = anon
/rest/mywebapp/** = authc, roles[Role1,Role2,Role3]
</value>
</property>
</bean>
In the code above i need a logical.OR kind of mapping to the /rest/mywebapp/** using the roles mentioned. This is possible via shiro annotations and it works but rather than specifying at every method i would rather handle it here (since i dont think shiro supports class level annotations yet ?) .
Is this possible ?
Also on a side note why is the authc filter not invoked ?
( for now we assume that the windows login can serve as authentication, using shiro only for authorization )
home page = meta refresh to /rest/secure/windowslogin/
if within intranet -> login ...
else /rest/secure/login ... login page.
Is it because the loginurl is different ? How do i circumvent this ? Note that my realm's getAuthorizationInfo is invoked though using the roles[ .. ] part specified in the config file.. but i was assuming that there should be a check to see if the request is 'authc' ? (which probably means that the filter is invoked and SubjectUtils.getSubject() is checked for authentication). Am i missing something in the flow or configuration ?
This is how shiro-security.xml looks like.
<bean id="customFilter1" class="com.pkg.RolesAuthorizationFilter">
<property name="roles" value="ROLE1,ROLE3,ROLE5"></property>
</bean>
<bean id="customFilter2" class="com.pkg.RolesAuthorizationFilter">
<property name="roles" value="ROLE1,ROLE2,ROLE5,ROLE6"></property>
</bean>
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<property name="securityManager" ref="securityManager" />
<property name="loginUrl" value="/login" />
<property name="successUrl" value="/home" />
<property name="unauthorizedUrl" value="/unauthorized" />
<property name="filters">
<util:map>
<entry key="authc">
<bean class="org.apache.shiro.web.filter.authc.PassThruAuthenticationFilter" />
</entry>
</util:map>
</property>
<property name="filterChainDefinitions">
<value>
/resources/** = anon
/login = anon
/logout = authc
/unauthorized = authc
/someurl/** = customFilter2
/** = customFilter1
</value>
</property>
</bean>
And this is RolesAuthorizationFilter class
package com.pkg;
import java.util.Arrays;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import org.apache.log4j.Logger;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.filter.authz.AuthorizationFilter;
public class RolesAuthorizationFilter extends AuthorizationFilter {
protected Logger logger = Logger.getLogger(this.getClass()
.getCanonicalName());
private String[] roles;
#Override
protected boolean isAccessAllowed(ServletRequest request,
ServletResponse response, Object mappedValue) throws Exception {
logger.info("= Roles = " + Arrays.toString(roles));
Subject subject = getSubject(request, response);
boolean allowAccess = false;
for (String role : roles) {
if (subject.hasRole(role)) {
logger.info("Authenticated role " + role);
allowAccess = true;
break;
}
}
return allowAccess;
}
public void setRoles(String[] roles) {
this.roles = roles;
}
}