BAEL-1273: add two test of the articles feed controller (#3794)

* BAEL-1216: improve tests

* BAEL-1448: Update Spring 5 articles to use the release version

* Setting up the Maven Wrapper on a maven project

* Add Maven Wrapper on spring-boot module

* simple add

* BAEL-976: Update spring version

* BAEL-1273: Display RSS feed with spring mvc (AbstractRssFeedView)

* Move RSS feed with Spring MVC from spring-boot to spring-mvc-simple

* BAEL-1285: Update Jackson articles

* BAEL-1273: implement both MVC and Rest approach to serve RSS content

* RSS(XML & Json) with a custom model

* BAEL-1273: remove a resource

* BAEL-1519: Guide to scribejava

* BAEL-1273: improve xml representation

* Fix pom

* BAEL-1587: JUnit 5 upgrade

* BAEL-1519: add GitHub implementation and improve article

* BAEL-1273: build a custom message converter to serve Rome Rss feed as json

* BAEL-1273: add two test of the articles feed controller

* Revert "BAEL-1273: add two test of the articles feed controller"

This reverts commit 3e4ced8a16.

* BAEL-1273: add two test of the articles feed controller

* Remove some others article files
This commit is contained in:
Dassi orleando
2018-03-10 01:48:11 +01:00
committed by maibin
parent 00b3a5148e
commit 42d3de85ba
20 changed files with 219 additions and 641 deletions

View File

@@ -1,17 +1,13 @@
package com.baeldung.spring.configuration;
import com.baeldung.spring.controller.rss.ArticleRssFeedViewResolver;
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import com.fasterxml.jackson.dataformat.xml.ser.ToXmlGenerator;
import com.baeldung.spring.controller.rss.JsonChannelHttpMessageConverter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.http.converter.feed.RssChannelHttpMessageConverter;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.http.converter.xml.MappingJackson2XmlHttpMessageConverter;
import org.springframework.web.accept.ContentNegotiationManager;
import org.springframework.web.multipart.MultipartResolver;
import org.springframework.web.multipart.commons.CommonsMultipartResolver;
@@ -28,7 +24,7 @@ import java.util.List;
@Configuration
@EnableWebMvc
@ComponentScan(basePackages = { "com.baeldung.springmvcforms", "com.baeldung.spring.controller", "com.baeldung.spring.validator" })
class ApplicationConfiguration extends WebMvcConfigurerAdapter {
public class ApplicationConfiguration extends WebMvcConfigurerAdapter {
@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
@@ -60,16 +56,9 @@ class ApplicationConfiguration extends WebMvcConfigurerAdapter {
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
Jackson2ObjectMapperBuilder builder = Jackson2ObjectMapperBuilder.xml();
builder.indentOutput(true);
XmlMapper xmlMapper = builder.createXmlMapper(true).build();
xmlMapper.configure(ToXmlGenerator.Feature.WRITE_XML_DECLARATION, true);
converters.add(new StringHttpMessageConverter());
converters.add(new RssChannelHttpMessageConverter());
converters.add(new MappingJackson2HttpMessageConverter());
converters.add(new MappingJackson2XmlHttpMessageConverter(xmlMapper));
converters.add(new JsonChannelHttpMessageConverter());
super.configureMessageConverters(converters);
}

View File

@@ -1,15 +1,14 @@
package com.baeldung.spring.controller.rss;
import java.io.Serializable;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
public class RssData implements Serializable {
public class Article implements Serializable {
private String link;
private String title;
private String description;
private String publishedDate;
private Date publishedDate;
private String author;
public String getLink() {
return link;
@@ -35,22 +34,30 @@ public class RssData implements Serializable {
this.description = description;
}
public String getPublishedDate() {
public Date getPublishedDate() {
return publishedDate;
}
public void setPublishedDate(Date publishedDate) {
DateFormat df = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss");
this.publishedDate = df.format(publishedDate);
this.publishedDate = publishedDate;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
@Override
public String toString() {
return "RssData{" +
return "Article{" +
"link='" + link + '\'' +
", title='" + title + '\'' +
", description='" + description + '\'' +
", publishedDate=" + publishedDate +
", author='" + author + '\'' +
'}';
}
}

View File

@@ -1,29 +0,0 @@
package com.baeldung.spring.controller.rss;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
@JacksonXmlRootElement(localName="articles")
public class ArticleFeed extends RssData implements Serializable {
@JacksonXmlProperty(localName = "item")
@JacksonXmlElementWrapper(useWrapping = false)
private List<ArticleItem> items = new ArrayList<ArticleItem>();
public void addItem(ArticleItem articleItem) {
this.items.add(articleItem);
}
public List<ArticleItem> getItems() {
return items;
}
public void setItems(List<ArticleItem> items) {
this.items = items;
}
}

View File

@@ -1,22 +0,0 @@
package com.baeldung.spring.controller.rss;
import java.io.Serializable;
public class ArticleItem extends RssData implements Serializable {
private String author;
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
@Override
public String toString() {
return "ArticleItem{" +
"author='" + author + '\'' +
'}';
}
}

View File

@@ -1,10 +1,15 @@
package com.baeldung.spring.controller.rss;
import com.rometools.rome.feed.rss.Channel;
import com.rometools.rome.feed.rss.Description;
import com.rometools.rome.feed.rss.Item;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
@Controller
public class ArticleRssController {
@@ -14,33 +19,53 @@ public class ArticleRssController {
return "articleFeedView";
}
@GetMapping(value = "/rss2")
@GetMapping(value = "/rss2", produces = {"application/rss+xml", "application/rss+json"})
@ResponseBody
public ArticleFeed articleRestFeed2() {
ArticleFeed feed = new ArticleFeed();
feed.setLink("http://localhost:8080/spring-mvc-simple/rss");
feed.setTitle("Article Feed");
feed.setDescription("Article Feed Description");
feed.setPublishedDate(new Date());
ArticleItem item1 = new ArticleItem();
public Channel articleHttpFeed() {
List<Article> items = new ArrayList<>();
Article item1 = new Article();
item1.setLink("http://www.baeldung.com/netty-exception-handling");
item1.setTitle("Exceptions in Netty");
item1.setDescription("In this quick article, well be looking at exception handling in Netty.");
item1.setPublishedDate(new Date());
item1.setAuthor("Carlos");
ArticleItem item2 = new ArticleItem();
Article item2 = new Article();
item2.setLink("http://www.baeldung.com/cockroachdb-java");
item2.setTitle("Guide to CockroachDB in Java");
item2.setDescription("This tutorial is an introductory guide to using CockroachDB with Java.");
item2.setPublishedDate(new Date());
item2.setAuthor("Baeldung");
feed.addItem(item1);
feed.addItem(item2);
items.add(item1);
items.add(item2);
Channel channelData = buildChannel(items);
return feed;
return channelData;
}
private Channel buildChannel(List<Article> articles){
Channel channel = new Channel("rss_2.0");
channel.setLink("http://localhost:8080/spring-mvc-simple/rss");
channel.setTitle("Article Feed");
channel.setDescription("Article Feed Description");
channel.setPubDate(new Date());
List<Item> items = new ArrayList<>();
for (Article article : articles) {
Item item = new Item();
item.setLink(article.getLink());
item.setTitle(article.getTitle());
Description description1 = new Description();
description1.setValue(article.getDescription());
item.setDescription(description1);
item.setPubDate(article.getPublishedDate());
item.setAuthor(article.getAuthor());
items.add(item);
}
channel.setItems(items);
return channel;
}
}

View File

@@ -0,0 +1,47 @@
package com.baeldung.spring.controller.rss;
import com.rometools.rome.feed.rss.Channel;
import com.rometools.rome.io.FeedException;
import com.rometools.rome.io.WireFeedOutput;
import org.json.JSONException;
import org.json.JSONObject;
import org.json.XML;
import org.springframework.http.HttpInputMessage;
import org.springframework.http.HttpOutputMessage;
import org.springframework.http.MediaType;
import org.springframework.http.converter.AbstractHttpMessageConverter;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.http.converter.HttpMessageNotWritableException;
import java.io.IOException;
public class JsonChannelHttpMessageConverter extends AbstractHttpMessageConverter<Channel> {
public JsonChannelHttpMessageConverter(){
super(new MediaType("application", "rss+json"));
}
@Override
protected boolean supports(Class<?> aClass) {
return Channel.class.isAssignableFrom(aClass);
}
@Override
protected Channel readInternal(Class<? extends Channel> aClass, HttpInputMessage httpInputMessage) throws IOException, HttpMessageNotReadableException {
return null;
}
@Override
protected void writeInternal(Channel wireFeed, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException {
WireFeedOutput feedOutput = new WireFeedOutput();
try {
String xmlStr = feedOutput.outputString(wireFeed, true);
JSONObject xmlJSONObj = XML.toJSONObject(xmlStr);
String jsonPrettyPrintString = xmlJSONObj.toString(4);
outputMessage.getBody().write(jsonPrettyPrintString.getBytes());
} catch (JSONException | FeedException e) {
e.printStackTrace();
}
}
}

View File

@@ -0,0 +1,58 @@
package com.baeldung.spring.controller.scribe;
import com.github.scribejava.apis.GitHubApi;
import com.github.scribejava.core.builder.ServiceBuilder;
import com.github.scribejava.core.model.*;
import com.github.scribejava.core.oauth.OAuth20Service;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.view.RedirectView;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.Random;
import java.util.concurrent.ExecutionException;
@Controller
@RequestMapping("github")
public class GithubController {
private OAuth20Service createService(String state) {
return new ServiceBuilder("e1f8d4f1a5c71467a159")
.apiSecret("4851597541a8f33a4f1bf1c70f3cedcfefbeb13b")
.state(state)
.callback("http://localhost:8080/spring-mvc-simple/github/callback")
.build(GitHubApi.instance());
}
@GetMapping(value = "/authorization")
public RedirectView authorization(HttpServletRequest servletReq) throws InterruptedException, ExecutionException, IOException {
String state = String.valueOf(new Random().nextInt(999_999));
OAuth20Service githubService = createService(state);
servletReq.getSession().setAttribute("state", state);
String authorizationUrl = githubService.getAuthorizationUrl();
RedirectView redirectView = new RedirectView();
redirectView.setUrl(authorizationUrl);
return redirectView;
}
@GetMapping(value = "/callback", produces = "text/plain")
@ResponseBody
public String callback(HttpServletRequest servletReq, @RequestParam("code") String code, @RequestParam("state") String state) throws InterruptedException, ExecutionException, IOException {
String initialState = (String) servletReq.getSession().getAttribute("state");
if(initialState.equals(state)) {
OAuth20Service githubService = createService(initialState);
OAuth2AccessToken accessToken = githubService.getAccessToken(code);
OAuthRequest request = new OAuthRequest(Verb.GET, "https://api.github.com/user");
githubService.signRequest(accessToken, request);
Response response = githubService.execute(request);
return response.getBody();
}
return "Error";
}
}

View File

@@ -17,18 +17,18 @@ import java.util.concurrent.ExecutionException;
@Controller
@RequestMapping("twitter")
public class ScribeController {
public class TwitterController {
private OAuth10aService createTwitterService() {
private OAuth10aService createService() {
return new ServiceBuilder("PSRszoHhRDVhyo2RIkThEbWko")
.apiSecret("prpJbz03DcGRN46sb4ucdSYtVxG8unUKhcnu3an5ItXbEOuenL")
.callback("http://localhost:8080/spring-mvc-simple/twitter/callback")
.build(TwitterApi.instance());
.apiSecret("prpJbz03DcGRN46sb4ucdSYtVxG8unUKhcnu3an5ItXbEOuenL")
.callback("http://localhost:8080/spring-mvc-simple/twitter/callback")
.build(TwitterApi.instance());
}
@GetMapping(value = "/authorization")
public RedirectView authorization(HttpServletRequest servletReq) throws InterruptedException, ExecutionException, IOException {
OAuth10aService twitterService = createTwitterService();
OAuth10aService twitterService = createService();
OAuth1RequestToken requestToken = twitterService.getRequestToken();
String authorizationUrl = twitterService.getAuthorizationUrl(requestToken);
@@ -42,7 +42,7 @@ public class ScribeController {
@GetMapping(value = "/callback", produces = "text/plain")
@ResponseBody
public String callback(HttpServletRequest servletReq, @RequestParam("oauth_verifier") String oauthV) throws InterruptedException, ExecutionException, IOException {
OAuth10aService twitterService = createTwitterService();
OAuth10aService twitterService = createService();
OAuth1RequestToken requestToken = (OAuth1RequestToken) servletReq.getSession().getAttribute("requestToken");
OAuth1AccessToken accessToken = twitterService.getAccessToken(requestToken, oauthV);

View File

@@ -0,0 +1,45 @@
package com.baeldung.controller.rss;
import com.baeldung.spring.configuration.ApplicationConfiguration;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.junit.jupiter.web.SpringJUnitWebConfig;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@SpringJUnitWebConfig(ApplicationConfiguration.class)
public class ArticleRssIntegrationTest {
public static final String APPLICATION_RSS_XML = "application/rss+xml";
public static final String APPLICATION_RSS_JSON = "application/rss+json";
public static final String APPLICATION_RSS_XML_CHARSET_UTF_8 = "application/rss+xml;charset=UTF-8";
@Autowired
private WebApplicationContext webAppContext;
private MockMvc mockMvc;
@BeforeEach
public void setup() {
mockMvc = MockMvcBuilders.webAppContextSetup(webAppContext)
.build();
}
@Test
public void whenRequestingXMLFeed_thenContentTypeIsOk() throws Exception {
mockMvc.perform(get("/rss2").accept(APPLICATION_RSS_XML))
.andExpect(status().isOk())
.andExpect(content().contentType(APPLICATION_RSS_XML_CHARSET_UTF_8));
}
@Test
public void whenRequestingJSONFeed_thenContentTypeIsOk() throws Exception {
mockMvc.perform(get("/rss2").accept(APPLICATION_RSS_JSON))
.andExpect(status().isOk())
.andExpect(content().contentType(APPLICATION_RSS_JSON));
}
}