commit 4e5741a4218c5a3748413624bfe1070239836ec2
parent eb9984c0b3bb4279d020741041a7d959efcdc048
Author: Wim Dupont <wim@wimdupont.com>
Date: Fri, 24 Feb 2023 00:47:48 +0100
fix rss - removed rome
Former-commit-id: 4413b056c571c0f1470dacabaa33256a668c45c7
Diffstat:
8 files changed, 258 insertions(+), 95 deletions(-)
diff --git a/pom.xml b/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
- <version>3.0.1</version>
+ <version>3.0.2</version>
</parent>
<groupId>com.wimdupont</groupId>
<artifactId>personalweb</artifactId>
@@ -16,8 +16,6 @@
<properties>
<java.version>17</java.version>
<asciidoctorj.version>2.5.7</asciidoctorj.version>
- <rome.version>1.0</rome.version>
- <rome.rometools.version>1.18.0</rome.rometools.version>
</properties>
<dependencies>
@@ -61,20 +59,10 @@
</exclusions>
</dependency>
<dependency>
- <groupId>com.rometools</groupId>
- <artifactId>rome</artifactId>
- <version>${rome.rometools.version}</version>
- </dependency>
- <dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-xml</artifactId>
</dependency>
<dependency>
- <groupId>rome</groupId>
- <artifactId>rome</artifactId>
- <version>${rome.version}</version>
- </dependency>
- <dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-core</artifactId>
</dependency>
diff --git a/src/main/java/com/wimdupont/personalweb/controller/FeedController.java b/src/main/java/com/wimdupont/personalweb/controller/FeedController.java
@@ -1,23 +1,30 @@
package com.wimdupont.personalweb.controller;
-import com.rometools.rome.feed.rss.Channel;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import com.wimdupont.personalweb.service.RssFeedGenerator;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
-import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;
+import static org.springframework.http.MediaType.APPLICATION_XML_VALUE;
+
@Controller
public class FeedController {
- private final RssFeedGenerator rssFeed;
+ private final RssFeedGenerator rssFeedGenerator;
- public FeedController(RssFeedGenerator rssFeed) {
- this.rssFeed = rssFeed;
+ public FeedController(RssFeedGenerator rssFeedGenerator) {
+ this.rssFeedGenerator = rssFeedGenerator;
}
@GetMapping(path = "/rss.xml")
- public @ResponseBody Channel getRss(Model model) {
- return rssFeed.getChannel();
+ @ResponseBody
+ public ResponseEntity<String> getRss() throws JsonProcessingException {
+ return ResponseEntity.ok()
+ .contentType(MediaType.parseMediaType(APPLICATION_XML_VALUE))
+ .body(new XmlMapper().writeValueAsString(rssFeedGenerator.getRssFeed()));
}
}
diff --git a/src/main/java/com/wimdupont/personalweb/model/rss/Channel.java b/src/main/java/com/wimdupont/personalweb/model/rss/Channel.java
@@ -0,0 +1,84 @@
+package com.wimdupont.personalweb.model.rss;
+
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper;
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
+
+import java.util.List;
+
+@JacksonXmlRootElement(localName = "channel")
+public record Channel(
+ @JacksonXmlProperty
+ String title,
+ @JacksonXmlProperty
+ String link,
+ @JacksonXmlProperty
+ String description,
+ @JacksonXmlProperty
+ String language,
+ @JacksonXmlProperty
+ String pubDate,
+ @JacksonXmlElementWrapper(useWrapping = false)
+ List<Item> item
+) {
+
+
+ private Channel(Builder builder) {
+ this(builder.title,
+ builder.link,
+ builder.description,
+ builder.language,
+ builder.pubDate,
+ builder.item);
+ }
+
+ public static final class Builder {
+ private @JacksonXmlProperty String title;
+ private @JacksonXmlProperty String link;
+ private @JacksonXmlProperty String description;
+ private @JacksonXmlProperty String language;
+ private @JacksonXmlProperty String pubDate;
+ private @JacksonXmlElementWrapper(useWrapping = false) List<Item> item;
+
+ private Builder() {
+ }
+
+ public static Builder newBuilder() {
+ return new Builder();
+ }
+
+ public Builder title(@JacksonXmlProperty String val) {
+ title = val;
+ return this;
+ }
+
+ public Builder link(@JacksonXmlProperty String val) {
+ link = val;
+ return this;
+ }
+
+ public Builder description(@JacksonXmlProperty String val) {
+ description = val;
+ return this;
+ }
+
+ public Builder language(@JacksonXmlProperty String val) {
+ language = val;
+ return this;
+ }
+
+ public Builder pubDate(@JacksonXmlProperty String val) {
+ pubDate = val;
+ return this;
+ }
+
+ public Builder item(@JacksonXmlElementWrapper(useWrapping = false) List<Item> val) {
+ item = val;
+ return this;
+ }
+
+ public Channel build() {
+ return new Channel(this);
+ }
+ }
+}
diff --git a/src/main/java/com/wimdupont/personalweb/model/rss/Item.java b/src/main/java/com/wimdupont/personalweb/model/rss/Item.java
@@ -0,0 +1,81 @@
+package com.wimdupont.personalweb.model.rss;
+
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
+
+@JacksonXmlRootElement(localName = "item")
+public record Item(
+ @JacksonXmlProperty
+ String title,
+ @JacksonXmlProperty
+ String description,
+ @JacksonXmlProperty
+ String link,
+ @JacksonXmlProperty
+ String author,
+ @JacksonXmlProperty
+ String pubDate,
+ @JacksonXmlProperty
+ String guid
+) {
+
+
+ private Item(Builder builder) {
+ this(builder.title,
+ builder.description,
+ builder.link,
+ builder.author,
+ builder.pubDate,
+ builder.guid);
+ }
+
+ public static final class Builder {
+ private @JacksonXmlProperty String title;
+ private @JacksonXmlProperty String description;
+ private @JacksonXmlProperty String link;
+ private @JacksonXmlProperty String author;
+ private @JacksonXmlProperty String pubDate;
+ private @JacksonXmlProperty String guid;
+
+ private Builder() {
+ }
+
+ public static Builder newBuilder() {
+ return new Builder();
+ }
+
+ public Builder title(@JacksonXmlProperty String val) {
+ title = val;
+ return this;
+ }
+
+ public Builder description(@JacksonXmlProperty String val) {
+ description = val;
+ return this;
+ }
+
+ public Builder link(@JacksonXmlProperty String val) {
+ link = val;
+ return this;
+ }
+
+ public Builder author(@JacksonXmlProperty String val) {
+ author = val;
+ return this;
+ }
+
+ public Builder pubDate(@JacksonXmlProperty String val) {
+ pubDate = val;
+ return this;
+ }
+
+ public Builder guid(@JacksonXmlProperty String val) {
+ guid = val;
+ return this;
+ }
+
+ public Item build() {
+ return new Item(this);
+ }
+ }
+}
diff --git a/src/main/java/com/wimdupont/personalweb/model/rss/RssFeed.java b/src/main/java/com/wimdupont/personalweb/model/rss/RssFeed.java
@@ -0,0 +1,45 @@
+package com.wimdupont.personalweb.model.rss;
+
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
+
+@JacksonXmlRootElement(localName = "rss")
+public record RssFeed(
+ @JacksonXmlProperty(localName = "channel")
+ Channel channel,
+
+ @JacksonXmlProperty(isAttribute = true)
+ String version
+) {
+
+ private RssFeed(Builder builder) {
+ this(builder.channel,
+ builder.version);
+ }
+
+ public static final class Builder {
+ private @JacksonXmlProperty(localName = "channel") Channel channel;
+ private @JacksonXmlProperty(isAttribute = true) String version;
+
+ private Builder() {
+ }
+
+ public static Builder newBuilder() {
+ return new Builder();
+ }
+
+ public Builder channel(@JacksonXmlProperty(localName = "channel") Channel val) {
+ channel = val;
+ return this;
+ }
+
+ public Builder version(@JacksonXmlProperty(isAttribute = true) String val) {
+ version = val;
+ return this;
+ }
+
+ public RssFeed build() {
+ return new RssFeed(this);
+ }
+ }
+}
diff --git a/src/main/java/com/wimdupont/personalweb/service/RssFeedGenerator.java b/src/main/java/com/wimdupont/personalweb/service/RssFeedGenerator.java
@@ -1,9 +1,8 @@
package com.wimdupont.personalweb.service;
-import com.rometools.rome.feed.rss.Channel;
-import com.rometools.rome.feed.rss.Content;
-import com.rometools.rome.feed.rss.Guid;
-import com.rometools.rome.feed.rss.Item;
+import com.wimdupont.personalweb.model.rss.Channel;
+import com.wimdupont.personalweb.model.rss.Item;
+import com.wimdupont.personalweb.model.rss.RssFeed;
import com.wimdupont.personalweb.util.Constants;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -11,10 +10,12 @@ import org.springframework.stereotype.Service;
import java.io.File;
import java.io.IOException;
+import java.time.Instant;
+import java.time.LocalDateTime;
+import java.time.ZoneId;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
-import java.util.Date;
import java.util.List;
@Service
@@ -22,29 +23,30 @@ public class RssFeedGenerator {
private static final Logger LOG = LoggerFactory.getLogger(RssFeedGenerator.class);
private final ArticleService articleService;
- private Channel channel;
+ private RssFeed rssFeed;
public RssFeedGenerator(ArticleService articleService) {
this.articleService = articleService;
}
- public Channel getChannel() {
- return channel;
+ public RssFeed getRssFeed() {
+ return rssFeed;
}
public void generate() {
- Channel channel = new Channel();
+ Channel channel = Channel.Builder.newBuilder()
+ .title("Wim Dupont")
+ .pubDate(LocalDateTime.now().toString())
+ .link("https://wimdupont.com")
+ .description("Updates from Wim Dupont")
+ .language("en-US")
+ .item(getItems())
+ .build();
- channel.setFeedType("rss_2.0");
- channel.setTitle("Wim Dupont");
- channel.setDescription("Updates from Wim Dupont");
- channel.setLink("https://wimdupont.com/rss.xml");
- channel.setUri("https://wimdupont.com/rss.xml");
- channel.setGenerator("Wim's Generatorâ„¢");
- channel.setPubDate(new Date());
- channel.setItems(getItems());
-
- this.channel = channel;
+ this.rssFeed = RssFeed.Builder.newBuilder()
+ .version("2.0")
+ .channel(channel)
+ .build();
}
private List<Item> getItems() {
@@ -62,28 +64,23 @@ public class RssFeedGenerator {
}
String title = article.getName().replace(Constants.HTML_SUFFIX, "");
- Item item = genericItem(new Date(article.lastModified()), title);
- item.setTitle(title);
- Content content = new Content();
- content.setValue(articleString);
- item.setContent(content);
- items.add(item);
+ LocalDateTime pubDate = Instant.ofEpochMilli(article.lastModified())
+ .atZone(ZoneId.systemDefault()).toLocalDateTime();
+ items.add(buildItem(pubDate, title, articleString));
}
}
return items;
}
- private Item genericItem(Date postDate, String title) {
+ private Item buildItem(LocalDateTime postDate, String title, String content) {
String url = String.format("https://wimdupont.com/blog/article/%s", title);
- Item item = new Item();
- item.setAuthor("Wim Dupont");
- item.setLink(url);
- item.setTitle(title);
- item.setUri(url);
- Guid guid = new Guid();
- guid.setValue(title + "-" + postDate.getTime());
- item.setGuid(guid);
- item.setPubDate(postDate);
- return item;
+ return Item.Builder.newBuilder()
+ .title(title)
+ .link(url)
+ .pubDate(postDate.toString())
+ .guid(title + "-" + postDate)
+ .author("Wim Dupont")
+ .description(content)
+ .build();
}
}
diff --git a/src/main/java/com/wimdupont/personalweb/service/SyndFeedService.java b/src/main/java/com/wimdupont/personalweb/service/SyndFeedService.java
@@ -1,25 +0,0 @@
-package com.wimdupont.personalweb.service;
-
-import com.rometools.rome.feed.synd.SyndFeed;
-import com.rometools.rome.io.FeedException;
-import com.rometools.rome.io.SyndFeedInput;
-import org.springframework.stereotype.Service;
-import org.xml.sax.InputSource;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URL;
-
-@Service
-public class SyndFeedService {
-
- public SyndFeed getSyndFeedForUrl(String url) throws IOException, IllegalArgumentException, FeedException {
- SyndFeed feed;
- try (InputStream inputStream = new URL(url).openConnection().getInputStream()) {
- InputSource source = new InputSource(inputStream);
- SyndFeedInput input = new SyndFeedInput();
- feed = input.build(source);
- }
- return feed;
- }
-}
diff --git a/src/main/java/com/wimdupont/personalweb/util/DateUtil.java b/src/main/java/com/wimdupont/personalweb/util/DateUtil.java
@@ -1,14 +0,0 @@
-package com.wimdupont.personalweb.util;
-
-import java.time.LocalDateTime;
-import java.time.ZoneId;
-import java.util.Date;
-
-public final class DateUtil {
- private DateUtil() {
- }
-
- public static LocalDateTime toLocalDateTime(Date date) {
- return date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
- }
-}