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:
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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 + '\'' +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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 + '\'' +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
@@ -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, we’ll 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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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";
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user