From edcff2ef2926512e45b481fd70ff9761ea7247fa Mon Sep 17 00:00:00 2001 From: Daniel Pelaez Date: Sat, 6 Apr 2024 19:47:00 -0500 Subject: [PATCH 01/13] Adding group field to publish posts by group --- .../repository/post/PostAWSRepository.java | 11 +++++ .../main/aws/repository/post/PostDynamo.java | 2 + .../src/main/resources/application.yml | 2 + .../abstraction/post/PostPublisher.java | 40 +++++++++++++------ .../abstraction/post/repository/Post.java | 3 ++ .../post/repository/PostRepository.java | 2 + .../main/controller/PostsController.java | 5 ++- .../main/factory/SpringPublisherFactory.java | 5 ++- 8 files changed, 54 insertions(+), 16 deletions(-) diff --git a/aws-publisher/src/main/java/com/coderstower/socialmediapubisher/springpublisher/main/aws/repository/post/PostAWSRepository.java b/aws-publisher/src/main/java/com/coderstower/socialmediapubisher/springpublisher/main/aws/repository/post/PostAWSRepository.java index 3e01472..c805c94 100644 --- a/aws-publisher/src/main/java/com/coderstower/socialmediapubisher/springpublisher/main/aws/repository/post/PostAWSRepository.java +++ b/aws-publisher/src/main/java/com/coderstower/socialmediapubisher/springpublisher/main/aws/repository/post/PostAWSRepository.java @@ -5,7 +5,9 @@ import java.util.Arrays; import java.util.Comparator; +import java.util.List; import java.util.Optional; +import java.util.stream.Collectors; import java.util.stream.StreamSupport; public class PostAWSRepository implements PostRepository { @@ -15,6 +17,13 @@ public PostAWSRepository(PostDynamoRepository postDynamoRepository) { this.postDynamoRepository = postDynamoRepository; } + @Override + public List findAll() { + return StreamSupport.stream(postDynamoRepository.findAll().spliterator(), false) + .map(this::convert) + .collect(Collectors.toList()); + } + @Override public Optional getNextToPublish() { return StreamSupport.stream(postDynamoRepository.findAll().spliterator(), false) @@ -35,6 +44,7 @@ private PostDynamo convert(Post post) { .name(post.getName()) .tags(post.getTags()) .url(post.getUrl()) + .group(post.getGroup()) .build(); } @@ -45,6 +55,7 @@ private Post convert(PostDynamo postDynamo) { .publishedDate(postDynamo.getPublishedDate()) .name(postDynamo.getName()) .tags(postDynamo.getTags()) + .group(postDynamo.getGroup()) .url(postDynamo.getUrl()).build(); } } diff --git a/aws-publisher/src/main/java/com/coderstower/socialmediapubisher/springpublisher/main/aws/repository/post/PostDynamo.java b/aws-publisher/src/main/java/com/coderstower/socialmediapubisher/springpublisher/main/aws/repository/post/PostDynamo.java index ade0426..3d80374 100644 --- a/aws-publisher/src/main/java/com/coderstower/socialmediapubisher/springpublisher/main/aws/repository/post/PostDynamo.java +++ b/aws-publisher/src/main/java/com/coderstower/socialmediapubisher/springpublisher/main/aws/repository/post/PostDynamo.java @@ -37,4 +37,6 @@ public class PostDynamo { @DynamoDBAttribute @DynamoDBTypeConverted(converter = LocalDateTimeConverter.class) private LocalDateTime publishedDate; + @DynamoDBAttribute + private String group; } diff --git a/aws-publisher/src/main/resources/application.yml b/aws-publisher/src/main/resources/application.yml index 2f70249..12907c1 100644 --- a/aws-publisher/src/main/resources/application.yml +++ b/aws-publisher/src/main/resources/application.yml @@ -5,6 +5,8 @@ # root: WARN social-media-publisher: + groups: + - java-quiz credentials: login-host: 'http://localhost:8080' login-url: '${social-media-publisher.credentials.login-host}/oauth2/{social-media-id}/credentials' diff --git a/spring-publisher/src/main/java/com/coderstower/socialmediapubisher/springpublisher/abstraction/post/PostPublisher.java b/spring-publisher/src/main/java/com/coderstower/socialmediapubisher/springpublisher/abstraction/post/PostPublisher.java index f5a0471..7b26e4b 100644 --- a/spring-publisher/src/main/java/com/coderstower/socialmediapubisher/springpublisher/abstraction/post/PostPublisher.java +++ b/spring-publisher/src/main/java/com/coderstower/socialmediapubisher/springpublisher/abstraction/post/PostPublisher.java @@ -8,6 +8,8 @@ import java.time.Clock; import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.Comparator; import java.util.List; import java.util.stream.Collectors; @@ -16,29 +18,43 @@ public class PostPublisher { private final PostRepository postRepository; private final Clock clock; - public PostPublisher(List socialMediaPublishers, PostRepository postRepository, Clock clock) { + private final List groupsToPublish; + + public PostPublisher(List socialMediaPublishers, PostRepository postRepository, Clock clock, List groupsToPublish) { this.socialMediaPublishers = socialMediaPublishers; this.postRepository = postRepository; this.clock = clock; + this.groupsToPublish = groupsToPublish; } - public Post publishNext() { + public List publishNext() { ping(socialMediaPublishers); - Post nextPost = postRepository.getNextToPublish() - .orElseThrow(() -> new IllegalStateException("There is not next post to publish")); + List posts = postRepository.findAll(); + List published = new ArrayList<>(); + + for (String group : groupsToPublish) { + Post nextPost = posts.stream() + .filter(post -> group.equals(post.getGroup())) + .min(Comparator.comparing(Post::getPublishedDate)) + .orElseThrow(() -> new IllegalStateException("There is not next post to publish")); + + List publishedPosts = publish(socialMediaPublishers, nextPost); - List publishedPosts = publish(socialMediaPublishers, nextPost); + if (publishedWellOK(publishedPosts)) { + Post toUpdate = nextPost.updateLastDatePublished(LocalDateTime.now(clock)); - if (publishedWellOK(publishedPosts)) { - Post toUpdate = nextPost.updateLastDatePublished(LocalDateTime.now(clock)); + Post publishedPost = postRepository.update(toUpdate) + .updatePublications(publishedPosts); - return postRepository.update(toUpdate) - .updatePublications(publishedPosts); - } else { - throw new IllegalStateException("Error publishing the post: " + nextPost - .updatePublications(publishedPosts)); + published.add(publishedPost); + } else { + throw new IllegalStateException("Error publishing the post: " + nextPost + .updatePublications(publishedPosts)); + } } + + return published; } private boolean publishedWellOK(List publishedPosts) { diff --git a/spring-publisher/src/main/java/com/coderstower/socialmediapubisher/springpublisher/abstraction/post/repository/Post.java b/spring-publisher/src/main/java/com/coderstower/socialmediapubisher/springpublisher/abstraction/post/repository/Post.java index 7f06d6f..3c5b945 100644 --- a/spring-publisher/src/main/java/com/coderstower/socialmediapubisher/springpublisher/abstraction/post/repository/Post.java +++ b/spring-publisher/src/main/java/com/coderstower/socialmediapubisher/springpublisher/abstraction/post/repository/Post.java @@ -22,6 +22,7 @@ public class Post { private final URL url; private final LocalDateTime publishedDate; private final List publications; + private final String group; public String basicFormat() { return String.format(BASIC_FORMAT, @@ -52,6 +53,7 @@ public Post updateLastDatePublished(LocalDateTime publishedDate) { .tags(tags) .url(url) .publications(publications) + .group(group) .publishedDate(publishedDate).build(); } @@ -63,6 +65,7 @@ public Post updatePublications(List publications) { .tags(tags) .url(url) .publications(publications) + .group(group) .publishedDate(publishedDate).build(); } } diff --git a/spring-publisher/src/main/java/com/coderstower/socialmediapubisher/springpublisher/abstraction/post/repository/PostRepository.java b/spring-publisher/src/main/java/com/coderstower/socialmediapubisher/springpublisher/abstraction/post/repository/PostRepository.java index 04ca2d8..fa77a77 100644 --- a/spring-publisher/src/main/java/com/coderstower/socialmediapubisher/springpublisher/abstraction/post/repository/PostRepository.java +++ b/spring-publisher/src/main/java/com/coderstower/socialmediapubisher/springpublisher/abstraction/post/repository/PostRepository.java @@ -1,8 +1,10 @@ package com.coderstower.socialmediapubisher.springpublisher.abstraction.post.repository; +import java.util.List; import java.util.Optional; public interface PostRepository { + List findAll(); Optional getNextToPublish(); Post update(Post post); } diff --git a/spring-publisher/src/main/java/com/coderstower/socialmediapubisher/springpublisher/main/controller/PostsController.java b/spring-publisher/src/main/java/com/coderstower/socialmediapubisher/springpublisher/main/controller/PostsController.java index bbe445b..82afba6 100644 --- a/spring-publisher/src/main/java/com/coderstower/socialmediapubisher/springpublisher/main/controller/PostsController.java +++ b/spring-publisher/src/main/java/com/coderstower/socialmediapubisher/springpublisher/main/controller/PostsController.java @@ -9,6 +9,7 @@ import org.springframework.web.bind.annotation.RestController; import java.util.HashMap; +import java.util.List; import java.util.Map; @RestController @@ -31,8 +32,8 @@ public Map ping() { } @RequestMapping(path = "/posts/next", method = RequestMethod.POST) - public Post postNext() { - Post post = postPublisher.publishNext(); + public List postNext() { + List post = postPublisher.publishNext(); log.info("Published Post: {}", post); diff --git a/spring-publisher/src/main/java/com/coderstower/socialmediapubisher/springpublisher/main/factory/SpringPublisherFactory.java b/spring-publisher/src/main/java/com/coderstower/socialmediapubisher/springpublisher/main/factory/SpringPublisherFactory.java index 0381f89..2c19556 100644 --- a/spring-publisher/src/main/java/com/coderstower/socialmediapubisher/springpublisher/main/factory/SpringPublisherFactory.java +++ b/spring-publisher/src/main/java/com/coderstower/socialmediapubisher/springpublisher/main/factory/SpringPublisherFactory.java @@ -8,6 +8,7 @@ import com.coderstower.socialmediapubisher.springpublisher.abstraction.security.repository.OAuth2CredentialsRepository; import com.coderstower.socialmediapubisher.springpublisher.main.socialmedia.linkedin.LinkedInPublisher; import com.coderstower.socialmediapubisher.springpublisher.main.socialmedia.twitter.TwitterPublisher; +import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -29,8 +30,8 @@ public Clock clock() { } @Bean - public PostPublisher postPublisher(List socialMediaPublishers, PostRepository postRepository, Clock clock) { - return new PostPublisher(socialMediaPublishers, postRepository, clock); + public PostPublisher postPublisher(List socialMediaPublishers, PostRepository postRepository, Clock clock, @Value("${social-media-publisher.groups}") List groups) { + return new PostPublisher(socialMediaPublishers, postRepository, clock, groups); } @Bean From 1bf5c7bd97ebd4ba1f1f8784c9a6e426fc8f2c28 Mon Sep 17 00:00:00 2001 From: Daniel Pelaez Date: Sat, 6 Apr 2024 19:48:21 -0500 Subject: [PATCH 02/13] Adding group field to publish posts by group --- .../main/aws/repository/post/PostAWSRepository.java | 7 ------- .../abstraction/post/repository/PostRepository.java | 2 -- 2 files changed, 9 deletions(-) diff --git a/aws-publisher/src/main/java/com/coderstower/socialmediapubisher/springpublisher/main/aws/repository/post/PostAWSRepository.java b/aws-publisher/src/main/java/com/coderstower/socialmediapubisher/springpublisher/main/aws/repository/post/PostAWSRepository.java index c805c94..35724c4 100644 --- a/aws-publisher/src/main/java/com/coderstower/socialmediapubisher/springpublisher/main/aws/repository/post/PostAWSRepository.java +++ b/aws-publisher/src/main/java/com/coderstower/socialmediapubisher/springpublisher/main/aws/repository/post/PostAWSRepository.java @@ -24,13 +24,6 @@ public List findAll() { .collect(Collectors.toList()); } - @Override - public Optional getNextToPublish() { - return StreamSupport.stream(postDynamoRepository.findAll().spliterator(), false) - .min(Comparator.comparing(PostDynamo::getPublishedDate)) - .map(this::convert); - } - @Override public Post update(Post post) { return convert(postDynamoRepository.save(convert(post))); diff --git a/spring-publisher/src/main/java/com/coderstower/socialmediapubisher/springpublisher/abstraction/post/repository/PostRepository.java b/spring-publisher/src/main/java/com/coderstower/socialmediapubisher/springpublisher/abstraction/post/repository/PostRepository.java index fa77a77..311f855 100644 --- a/spring-publisher/src/main/java/com/coderstower/socialmediapubisher/springpublisher/abstraction/post/repository/PostRepository.java +++ b/spring-publisher/src/main/java/com/coderstower/socialmediapubisher/springpublisher/abstraction/post/repository/PostRepository.java @@ -1,10 +1,8 @@ package com.coderstower.socialmediapubisher.springpublisher.abstraction.post.repository; import java.util.List; -import java.util.Optional; public interface PostRepository { List findAll(); - Optional getNextToPublish(); Post update(Post post); } From dcefa466dd0e099a03548bc5b5e6996244a4c89d Mon Sep 17 00:00:00 2001 From: Daniel Pelaez Date: Sun, 7 Apr 2024 09:55:32 -0500 Subject: [PATCH 03/13] Adding group field to publish posts by group --- .../abstraction/post/PostPublisherTest.java | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/spring-publisher/src/test/java/com/coderstower/socialmediapubisher/springpublisher/abstraction/post/PostPublisherTest.java b/spring-publisher/src/test/java/com/coderstower/socialmediapubisher/springpublisher/abstraction/post/PostPublisherTest.java index 8d291b0..b4e38da 100644 --- a/spring-publisher/src/test/java/com/coderstower/socialmediapubisher/springpublisher/abstraction/post/PostPublisherTest.java +++ b/spring-publisher/src/test/java/com/coderstower/socialmediapubisher/springpublisher/abstraction/post/PostPublisherTest.java @@ -37,7 +37,7 @@ class PostPublisherTest { @BeforeEach public void before() { this.postPublisher = new PostPublisher(List.of(socialMediaPublisher1, socialMediaPublisher2), postRepository, Clock - .fixed(ZonedDateTime.of(2020, 3, 3, 5, 6, 8, 1, ZoneId.of("UTC")).toInstant(), ZoneId.of("UTC"))); + .fixed(ZonedDateTime.of(2020, 3, 3, 5, 6, 8, 1, ZoneId.of("UTC")).toInstant(), ZoneId.of("UTC")), List.of("group1")); } @Test @@ -56,7 +56,7 @@ public void publishNext_pingFailed_exception() { @Test public void publishNext_noPost_exception() { - when(postRepository.getNextToPublish()).thenReturn(Optional.empty()); + when(postRepository.findAll()).thenReturn(List.of()); when(socialMediaPublisher1.ping()).thenReturn(Acknowledge.builder() .status(Acknowledge.Status.SUCCESS).build()); when(socialMediaPublisher2.ping()).thenReturn(Acknowledge.builder() @@ -76,6 +76,7 @@ public void publishNext_publishFailed_exception() throws MalformedURLException { .publishedDate(LocalDateTime.of(2020, 2, 3, 5, 6, 8, 1)) .tags(List.of("tag1", "tag2")) .url(URI.create("https://myblog/post").toURL()) + .group("group1") .build(); Post expectedPost = Post.builder() @@ -85,6 +86,7 @@ public void publishNext_publishFailed_exception() throws MalformedURLException { .publishedDate(LocalDateTime.of(2020, 2, 3, 5, 6, 8, 1)) .tags(List.of("tag1", "tag2")) .url(URI.create("https://myblog/post").toURL()) + .group("group1") .publications(List .of(Publication.builder() .id("id") @@ -99,7 +101,7 @@ public void publishNext_publishFailed_exception() throws MalformedURLException { .build())) .build(); - when(postRepository.getNextToPublish()).thenReturn(Optional.of(post)); + when(postRepository.findAll()).thenReturn(List.of(post)); when(socialMediaPublisher1.ping()).thenReturn(Acknowledge.builder() .status(Acknowledge.Status.SUCCESS).build()); when(socialMediaPublisher1.publish(post)).thenReturn(Publication.builder() @@ -130,6 +132,7 @@ public void publishNext_publishSuccess_publications() throws MalformedURLExcepti .publishedDate(LocalDateTime.of(2020, 2, 3, 5, 6, 8, 1)) .tags(List.of("tag1", "tag2")) .url(URI.create("https://myblog/post").toURL()) + .group("group1") .build(); Post postUpdated = Post.builder() @@ -139,6 +142,7 @@ public void publishNext_publishSuccess_publications() throws MalformedURLExcepti .publishedDate(LocalDateTime.of(2020, 3, 3, 5, 6, 8, 1)) .tags(List.of("tag1", "tag2")) .url(URI.create("https://myblog/post").toURL()) + .group("group1") .build(); Post expectedPost = Post.builder() @@ -148,6 +152,7 @@ public void publishNext_publishSuccess_publications() throws MalformedURLExcepti .publishedDate(LocalDateTime.of(2020, 3, 3, 5, 6, 8, 1)) .tags(List.of("tag1", "tag2")) .url(URI.create("https://myblog/post").toURL()) + .group("group1") .publications(List .of(Publication.builder() .id("id") @@ -163,7 +168,7 @@ public void publishNext_publishSuccess_publications() throws MalformedURLExcepti .build())) .build(); - when(postRepository.getNextToPublish()).thenReturn(Optional.of(post)); + when(postRepository.findAll()).thenReturn(List.of(post)); when(socialMediaPublisher1.ping()).thenReturn(Acknowledge.builder() .status(Acknowledge.Status.SUCCESS).build()); when(socialMediaPublisher1.publish(post)).thenReturn(Publication.builder() @@ -182,9 +187,9 @@ public void publishNext_publishSuccess_publications() throws MalformedURLExcepti .build()); when(postRepository.update(postUpdated)).thenReturn(postUpdated); - Post publishedPost = postPublisher.publishNext(); + List publishedPost = postPublisher.publishNext(); - assertThat(publishedPost).isEqualTo(expectedPost); + assertThat(publishedPost).isEqualTo(List.of(expectedPost)); } } \ No newline at end of file From 47d9c0ddd622f4f5a1a82081b1619b867d0b3004 Mon Sep 17 00:00:00 2001 From: Daniel Pelaez Date: Sun, 7 Apr 2024 10:04:17 -0500 Subject: [PATCH 04/13] Adding group field to publish posts by group --- spring-publisher/pom.xml | 2 +- .../main/controller/PostsControllerTest.java | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/spring-publisher/pom.xml b/spring-publisher/pom.xml index f9cabbd..43ddecd 100644 --- a/spring-publisher/pom.xml +++ b/spring-publisher/pom.xml @@ -30,7 +30,7 @@ org.twitter4j twitter4j-core - [4.0,) + 4.0.0 diff --git a/spring-publisher/src/test/java/com/coderstower/socialmediapubisher/springpublisher/main/controller/PostsControllerTest.java b/spring-publisher/src/test/java/com/coderstower/socialmediapubisher/springpublisher/main/controller/PostsControllerTest.java index 35ccfca..9ab2fac 100644 --- a/spring-publisher/src/test/java/com/coderstower/socialmediapubisher/springpublisher/main/controller/PostsControllerTest.java +++ b/spring-publisher/src/test/java/com/coderstower/socialmediapubisher/springpublisher/main/controller/PostsControllerTest.java @@ -38,7 +38,7 @@ public void ping(){ @Test public void postNext() throws MalformedURLException { - when(postPublisher.publishNext()).thenReturn(Post.builder() + when(postPublisher.publishNext()).thenReturn(List.of(Post.builder() .id("2") .name("My Post 2") .description("My second post") @@ -49,11 +49,11 @@ public void postNext() throws MalformedURLException { .status(Publication.Status.FAILURE) .publisher("twitter") .build())) - .build()); + .build())); - Post result = postsController.postNext(); + List result = postsController.postNext(); - assertThat(result).isEqualTo(Post.builder() + assertThat(result).isEqualTo(List.of(Post.builder() .id("2") .name("My Post 2") .description("My second post") @@ -64,7 +64,7 @@ public void postNext() throws MalformedURLException { .status(Publication.Status.FAILURE) .publisher("twitter") .build())) - .build()); + .build())); } } \ No newline at end of file From bc970811c9c5c49eaaed7475cc5907cbae15629e Mon Sep 17 00:00:00 2001 From: Daniel Pelaez Date: Sun, 7 Apr 2024 10:16:13 -0500 Subject: [PATCH 05/13] Adding group field to publish posts by group --- .../post/PostAWSRepositoryTest.java | 30 +++++++++++++------ 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/aws-publisher/src/test/java/com/coderstower/socialmediapubisher/springpublisher/main/aws/repository/post/PostAWSRepositoryTest.java b/aws-publisher/src/test/java/com/coderstower/socialmediapubisher/springpublisher/main/aws/repository/post/PostAWSRepositoryTest.java index f9310ea..48a5154 100644 --- a/aws-publisher/src/test/java/com/coderstower/socialmediapubisher/springpublisher/main/aws/repository/post/PostAWSRepositoryTest.java +++ b/aws-publisher/src/test/java/com/coderstower/socialmediapubisher/springpublisher/main/aws/repository/post/PostAWSRepositoryTest.java @@ -30,6 +30,7 @@ public void getNextToPublish() throws MalformedURLException { .name("My Post 2") .description("My second post") .tags(List.of("tag1", "tag2")) + .group("group1") .url(URI.create("https://coderstower.com/2020/01/13/open-close-principle-by-example/").toURL()) .publishedDate(LocalDateTime.parse("2012-09-17T18:47:52")) .build(), PostDynamo.builder() @@ -37,20 +38,31 @@ public void getNextToPublish() throws MalformedURLException { .name("My Post 1") .description("My first post") .tags(List.of("tag1", "tag2")) + .group("group1") .url(URI.create("https://coderstower.com/2020/02/18/unit-tests-vs-integration-tests/").toURL()) .publishedDate(LocalDateTime.parse("2013-09-17T18:47:52")) .build())); - Optional post = postAWSRepository.getNextToPublish(); + List post = postAWSRepository.findAll(); - assertThat(post).isEqualTo(Optional.of(Post.builder() - .id("2") - .name("My Post 2") - .description("My second post") - .tags(List.of("tag1", "tag2")) - .url(URI.create("https://coderstower.com/2020/01/13/open-close-principle-by-example/").toURL()) - .publishedDate(LocalDateTime.parse("2012-09-17T18:47:52")) - .build())); + assertThat(post).isEqualTo(List.of(Post.builder() + .id("2") + .name("My Post 2") + .description("My second post") + .tags(List.of("tag1", "tag2")) + .group("group1") + .url(URI.create("https://coderstower.com/2020/01/13/open-close-principle-by-example/").toURL()) + .publishedDate(LocalDateTime.parse("2012-09-17T18:47:52")) + .build(), + Post.builder() + .id("1") + .name("My Post 1") + .description("My first post") + .tags(List.of("tag1", "tag2")) + .group("group1") + .url(URI.create("https://coderstower.com/2020/02/18/unit-tests-vs-integration-tests/").toURL()) + .publishedDate(LocalDateTime.parse("2013-09-17T18:47:52")) + .build())); } @Test From dd75fdeb9995991fe55daaa2f0ba9fb4b5128cad Mon Sep 17 00:00:00 2001 From: Daniel Pelaez Date: Sun, 7 Apr 2024 12:20:40 -0500 Subject: [PATCH 06/13] Adding group field to publish posts by group --- aws-publisher/pom.xml | 2 +- spring-publisher/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/aws-publisher/pom.xml b/aws-publisher/pom.xml index a9e7f02..7f14d54 100644 --- a/aws-publisher/pom.xml +++ b/aws-publisher/pom.xml @@ -45,7 +45,7 @@ com.amazonaws DynamoDBLocal - [1.12,2.0) + 1.13.0 test diff --git a/spring-publisher/pom.xml b/spring-publisher/pom.xml index 43ddecd..5f85380 100644 --- a/spring-publisher/pom.xml +++ b/spring-publisher/pom.xml @@ -30,7 +30,7 @@ org.twitter4j twitter4j-core - 4.0.0 + 4.0.7 From e600b251828b7483a332d67ab9770d2994dbc0dd Mon Sep 17 00:00:00 2001 From: Daniel Pelaez Date: Sun, 7 Apr 2024 12:30:50 -0500 Subject: [PATCH 07/13] Adding group field to publish posts by group --- aws-publisher/src/main/resources/application.yml | 2 +- .../main/aws/MockSocialMediaSuccessfulTests.java | 2 ++ .../main/factory/SocialMediaPublisherProperties.java | 2 ++ .../springpublisher/main/factory/SpringPublisherFactory.java | 4 ++-- 4 files changed, 7 insertions(+), 3 deletions(-) diff --git a/aws-publisher/src/main/resources/application.yml b/aws-publisher/src/main/resources/application.yml index 12907c1..03031d2 100644 --- a/aws-publisher/src/main/resources/application.yml +++ b/aws-publisher/src/main/resources/application.yml @@ -6,7 +6,7 @@ social-media-publisher: groups: - - java-quiz + - group1 credentials: login-host: 'http://localhost:8080' login-url: '${social-media-publisher.credentials.login-host}/oauth2/{social-media-id}/credentials' diff --git a/aws-publisher/src/test/java/com/coderstower/socialmediapubisher/springpublisher/main/aws/MockSocialMediaSuccessfulTests.java b/aws-publisher/src/test/java/com/coderstower/socialmediapubisher/springpublisher/main/aws/MockSocialMediaSuccessfulTests.java index b5a516d..6ed735c 100644 --- a/aws-publisher/src/test/java/com/coderstower/socialmediapubisher/springpublisher/main/aws/MockSocialMediaSuccessfulTests.java +++ b/aws-publisher/src/test/java/com/coderstower/socialmediapubisher/springpublisher/main/aws/MockSocialMediaSuccessfulTests.java @@ -183,6 +183,7 @@ public AmazonDynamoDB amazonDynamoDB() { post1.addItemEntry("tags", new AttributeValue().withL(new AttributeValue("tag1"), new AttributeValue("tag2"))); post1.addItemEntry("url", new AttributeValue("https://coderstower.com/2020/02/18/unit-tests-vs-integration-tests/")); post1.addItemEntry("publishedDate", new AttributeValue("2013-09-17T18:47:52")); + post1.addItemEntry("group", new AttributeValue("group1")); ddb.putItem(post1); @@ -194,6 +195,7 @@ public AmazonDynamoDB amazonDynamoDB() { post2.addItemEntry("tags", new AttributeValue().withL(new AttributeValue("tag1"), new AttributeValue("tag2"))); post2.addItemEntry("url", new AttributeValue("https://coderstower.com/2020/01/13/open-close-principle-by-example/")); post2.addItemEntry("publishedDate", new AttributeValue("2012-09-17T18:47:52")); + post2.addItemEntry("group", new AttributeValue("group1")); ddb.putItem(post2); diff --git a/spring-publisher/src/main/java/com/coderstower/socialmediapubisher/springpublisher/main/factory/SocialMediaPublisherProperties.java b/spring-publisher/src/main/java/com/coderstower/socialmediapubisher/springpublisher/main/factory/SocialMediaPublisherProperties.java index a47c283..2498817 100644 --- a/spring-publisher/src/main/java/com/coderstower/socialmediapubisher/springpublisher/main/factory/SocialMediaPublisherProperties.java +++ b/spring-publisher/src/main/java/com/coderstower/socialmediapubisher/springpublisher/main/factory/SocialMediaPublisherProperties.java @@ -5,6 +5,7 @@ import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.ConstructorBinding; +import java.util.List; import java.util.Map; @ConfigurationProperties(prefix = "social-media-publisher") @@ -14,4 +15,5 @@ public class SocialMediaPublisherProperties { private final Map principalNamesAllowed; private final CredentialsProperties credentials; + private final List groups; } diff --git a/spring-publisher/src/main/java/com/coderstower/socialmediapubisher/springpublisher/main/factory/SpringPublisherFactory.java b/spring-publisher/src/main/java/com/coderstower/socialmediapubisher/springpublisher/main/factory/SpringPublisherFactory.java index 2c19556..d887b23 100644 --- a/spring-publisher/src/main/java/com/coderstower/socialmediapubisher/springpublisher/main/factory/SpringPublisherFactory.java +++ b/spring-publisher/src/main/java/com/coderstower/socialmediapubisher/springpublisher/main/factory/SpringPublisherFactory.java @@ -30,8 +30,8 @@ public Clock clock() { } @Bean - public PostPublisher postPublisher(List socialMediaPublishers, PostRepository postRepository, Clock clock, @Value("${social-media-publisher.groups}") List groups) { - return new PostPublisher(socialMediaPublishers, postRepository, clock, groups); + public PostPublisher postPublisher(List socialMediaPublishers, PostRepository postRepository, Clock clock, SocialMediaPublisherProperties socialMediaPublisherProperties) { + return new PostPublisher(socialMediaPublishers, postRepository, clock, socialMediaPublisherProperties.getGroups()); } @Bean From cf072446a0ab420a648dcdf38364e51cd88ac6f6 Mon Sep 17 00:00:00 2001 From: Daniel Pelaez Date: Sun, 7 Apr 2024 18:44:03 -0500 Subject: [PATCH 08/13] Adding group field to publish posts by group --- .../repository/post/PostAWSRepository.java | 9 ++--- .../abstraction/post/PostPublisher.java | 40 ++++++------------- .../post/repository/PostRepository.java | 4 +- .../main/controller/PostsController.java | 10 ++--- .../SocialMediaPublisherProperties.java | 2 - .../main/factory/SpringPublisherFactory.java | 5 +-- .../abstraction/post/PostPublisherTest.java | 9 ++--- .../main/controller/PostsControllerTest.java | 2 +- 8 files changed, 30 insertions(+), 51 deletions(-) diff --git a/aws-publisher/src/main/java/com/coderstower/socialmediapubisher/springpublisher/main/aws/repository/post/PostAWSRepository.java b/aws-publisher/src/main/java/com/coderstower/socialmediapubisher/springpublisher/main/aws/repository/post/PostAWSRepository.java index 35724c4..babb954 100644 --- a/aws-publisher/src/main/java/com/coderstower/socialmediapubisher/springpublisher/main/aws/repository/post/PostAWSRepository.java +++ b/aws-publisher/src/main/java/com/coderstower/socialmediapubisher/springpublisher/main/aws/repository/post/PostAWSRepository.java @@ -5,9 +5,7 @@ import java.util.Arrays; import java.util.Comparator; -import java.util.List; import java.util.Optional; -import java.util.stream.Collectors; import java.util.stream.StreamSupport; public class PostAWSRepository implements PostRepository { @@ -18,10 +16,11 @@ public PostAWSRepository(PostDynamoRepository postDynamoRepository) { } @Override - public List findAll() { + public Optional getNextToPublish(String group) { return StreamSupport.stream(postDynamoRepository.findAll().spliterator(), false) - .map(this::convert) - .collect(Collectors.toList()); + .filter(postDynamo -> group.equals(postDynamo.getGroup())) + .min(Comparator.comparing(PostDynamo::getPublishedDate)) + .map(this::convert); } @Override diff --git a/spring-publisher/src/main/java/com/coderstower/socialmediapubisher/springpublisher/abstraction/post/PostPublisher.java b/spring-publisher/src/main/java/com/coderstower/socialmediapubisher/springpublisher/abstraction/post/PostPublisher.java index 7b26e4b..484cc18 100644 --- a/spring-publisher/src/main/java/com/coderstower/socialmediapubisher/springpublisher/abstraction/post/PostPublisher.java +++ b/spring-publisher/src/main/java/com/coderstower/socialmediapubisher/springpublisher/abstraction/post/PostPublisher.java @@ -8,8 +8,6 @@ import java.time.Clock; import java.time.LocalDateTime; -import java.util.ArrayList; -import java.util.Comparator; import java.util.List; import java.util.stream.Collectors; @@ -18,43 +16,29 @@ public class PostPublisher { private final PostRepository postRepository; private final Clock clock; - private final List groupsToPublish; - - public PostPublisher(List socialMediaPublishers, PostRepository postRepository, Clock clock, List groupsToPublish) { + public PostPublisher(List socialMediaPublishers, PostRepository postRepository, Clock clock) { this.socialMediaPublishers = socialMediaPublishers; this.postRepository = postRepository; this.clock = clock; - this.groupsToPublish = groupsToPublish; } - public List publishNext() { + public Post publishNext(String group) { ping(socialMediaPublishers); - List posts = postRepository.findAll(); - List published = new ArrayList<>(); - - for (String group : groupsToPublish) { - Post nextPost = posts.stream() - .filter(post -> group.equals(post.getGroup())) - .min(Comparator.comparing(Post::getPublishedDate)) - .orElseThrow(() -> new IllegalStateException("There is not next post to publish")); - - List publishedPosts = publish(socialMediaPublishers, nextPost); + Post nextPost = postRepository.getNextToPublish(group) + .orElseThrow(() -> new IllegalStateException("There is not next post to publish")); - if (publishedWellOK(publishedPosts)) { - Post toUpdate = nextPost.updateLastDatePublished(LocalDateTime.now(clock)); + List publishedPosts = publish(socialMediaPublishers, nextPost); - Post publishedPost = postRepository.update(toUpdate) - .updatePublications(publishedPosts); + if (publishedWellOK(publishedPosts)) { + Post toUpdate = nextPost.updateLastDatePublished(LocalDateTime.now(clock)); - published.add(publishedPost); - } else { - throw new IllegalStateException("Error publishing the post: " + nextPost - .updatePublications(publishedPosts)); - } + return postRepository.update(toUpdate) + .updatePublications(publishedPosts); + } else { + throw new IllegalStateException("Error publishing the post: " + nextPost + .updatePublications(publishedPosts)); } - - return published; } private boolean publishedWellOK(List publishedPosts) { diff --git a/spring-publisher/src/main/java/com/coderstower/socialmediapubisher/springpublisher/abstraction/post/repository/PostRepository.java b/spring-publisher/src/main/java/com/coderstower/socialmediapubisher/springpublisher/abstraction/post/repository/PostRepository.java index 311f855..19ad73f 100644 --- a/spring-publisher/src/main/java/com/coderstower/socialmediapubisher/springpublisher/abstraction/post/repository/PostRepository.java +++ b/spring-publisher/src/main/java/com/coderstower/socialmediapubisher/springpublisher/abstraction/post/repository/PostRepository.java @@ -1,8 +1,8 @@ package com.coderstower.socialmediapubisher.springpublisher.abstraction.post.repository; -import java.util.List; +import java.util.Optional; public interface PostRepository { - List findAll(); + Optional getNextToPublish(String group); Post update(Post post); } diff --git a/spring-publisher/src/main/java/com/coderstower/socialmediapubisher/springpublisher/main/controller/PostsController.java b/spring-publisher/src/main/java/com/coderstower/socialmediapubisher/springpublisher/main/controller/PostsController.java index 82afba6..6201df2 100644 --- a/spring-publisher/src/main/java/com/coderstower/socialmediapubisher/springpublisher/main/controller/PostsController.java +++ b/spring-publisher/src/main/java/com/coderstower/socialmediapubisher/springpublisher/main/controller/PostsController.java @@ -4,12 +4,12 @@ import com.coderstower.socialmediapubisher.springpublisher.abstraction.post.PostPublisher; import com.coderstower.socialmediapubisher.springpublisher.abstraction.post.repository.Post; import lombok.extern.slf4j.Slf4j; +import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; import java.util.HashMap; -import java.util.List; import java.util.Map; @RestController @@ -31,11 +31,11 @@ public Map ping() { return pong; } - @RequestMapping(path = "/posts/next", method = RequestMethod.POST) - public List postNext() { - List post = postPublisher.publishNext(); + @RequestMapping(path = "/posts/{group}/next", method = RequestMethod.POST) + public Post postNext(@PathVariable String group) { + Post post = postPublisher.publishNext(group); - log.info("Published Post: {}", post); + log.info("Published Post from group {}: {}", group, post); return post; } diff --git a/spring-publisher/src/main/java/com/coderstower/socialmediapubisher/springpublisher/main/factory/SocialMediaPublisherProperties.java b/spring-publisher/src/main/java/com/coderstower/socialmediapubisher/springpublisher/main/factory/SocialMediaPublisherProperties.java index 2498817..a47c283 100644 --- a/spring-publisher/src/main/java/com/coderstower/socialmediapubisher/springpublisher/main/factory/SocialMediaPublisherProperties.java +++ b/spring-publisher/src/main/java/com/coderstower/socialmediapubisher/springpublisher/main/factory/SocialMediaPublisherProperties.java @@ -5,7 +5,6 @@ import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.ConstructorBinding; -import java.util.List; import java.util.Map; @ConfigurationProperties(prefix = "social-media-publisher") @@ -15,5 +14,4 @@ public class SocialMediaPublisherProperties { private final Map principalNamesAllowed; private final CredentialsProperties credentials; - private final List groups; } diff --git a/spring-publisher/src/main/java/com/coderstower/socialmediapubisher/springpublisher/main/factory/SpringPublisherFactory.java b/spring-publisher/src/main/java/com/coderstower/socialmediapubisher/springpublisher/main/factory/SpringPublisherFactory.java index d887b23..0381f89 100644 --- a/spring-publisher/src/main/java/com/coderstower/socialmediapubisher/springpublisher/main/factory/SpringPublisherFactory.java +++ b/spring-publisher/src/main/java/com/coderstower/socialmediapubisher/springpublisher/main/factory/SpringPublisherFactory.java @@ -8,7 +8,6 @@ import com.coderstower.socialmediapubisher.springpublisher.abstraction.security.repository.OAuth2CredentialsRepository; import com.coderstower.socialmediapubisher.springpublisher.main.socialmedia.linkedin.LinkedInPublisher; import com.coderstower.socialmediapubisher.springpublisher.main.socialmedia.twitter.TwitterPublisher; -import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -30,8 +29,8 @@ public Clock clock() { } @Bean - public PostPublisher postPublisher(List socialMediaPublishers, PostRepository postRepository, Clock clock, SocialMediaPublisherProperties socialMediaPublisherProperties) { - return new PostPublisher(socialMediaPublishers, postRepository, clock, socialMediaPublisherProperties.getGroups()); + public PostPublisher postPublisher(List socialMediaPublishers, PostRepository postRepository, Clock clock) { + return new PostPublisher(socialMediaPublishers, postRepository, clock); } @Bean diff --git a/spring-publisher/src/test/java/com/coderstower/socialmediapubisher/springpublisher/abstraction/post/PostPublisherTest.java b/spring-publisher/src/test/java/com/coderstower/socialmediapubisher/springpublisher/abstraction/post/PostPublisherTest.java index b4e38da..0a9649e 100644 --- a/spring-publisher/src/test/java/com/coderstower/socialmediapubisher/springpublisher/abstraction/post/PostPublisherTest.java +++ b/spring-publisher/src/test/java/com/coderstower/socialmediapubisher/springpublisher/abstraction/post/PostPublisherTest.java @@ -18,7 +18,6 @@ import java.time.ZoneId; import java.time.ZonedDateTime; import java.util.List; -import java.util.Optional; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertThrows; @@ -48,7 +47,7 @@ public void publishNext_pingFailed_exception() { .status(Acknowledge.Status.FAILURE).build()); when(socialMediaPublisher2.getName()).thenReturn("LINKEDIN"); - IllegalStateException exception = assertThrows(IllegalStateException.class, () -> postPublisher.publishNext()); + IllegalStateException exception = assertThrows(IllegalStateException.class, () -> postPublisher.publishNext(group)); assertThat(exception.getMessage()).isEqualTo("Ping to LINKEDIN failed: " + Acknowledge.builder() .status(Acknowledge.Status.FAILURE).build()); @@ -62,7 +61,7 @@ public void publishNext_noPost_exception() { when(socialMediaPublisher2.ping()).thenReturn(Acknowledge.builder() .status(Acknowledge.Status.SUCCESS).build()); - IllegalStateException exception = assertThrows(IllegalStateException.class, () -> postPublisher.publishNext()); + IllegalStateException exception = assertThrows(IllegalStateException.class, () -> postPublisher.publishNext(group)); assertThat(exception.getMessage()).isEqualTo("There is not next post to publish"); } @@ -118,7 +117,7 @@ public void publishNext_publishFailed_exception() throws MalformedURLException { .publisher("LINKEDIN") .build()); - IllegalStateException exception = assertThrows(IllegalStateException.class, () -> postPublisher.publishNext()); + IllegalStateException exception = assertThrows(IllegalStateException.class, () -> postPublisher.publishNext(group)); assertThat(exception.getMessage()).isEqualTo("Error publishing the post: " + expectedPost); } @@ -187,7 +186,7 @@ public void publishNext_publishSuccess_publications() throws MalformedURLExcepti .build()); when(postRepository.update(postUpdated)).thenReturn(postUpdated); - List publishedPost = postPublisher.publishNext(); + List publishedPost = postPublisher.publishNext(group); assertThat(publishedPost).isEqualTo(List.of(expectedPost)); } diff --git a/spring-publisher/src/test/java/com/coderstower/socialmediapubisher/springpublisher/main/controller/PostsControllerTest.java b/spring-publisher/src/test/java/com/coderstower/socialmediapubisher/springpublisher/main/controller/PostsControllerTest.java index 9ab2fac..64e3425 100644 --- a/spring-publisher/src/test/java/com/coderstower/socialmediapubisher/springpublisher/main/controller/PostsControllerTest.java +++ b/spring-publisher/src/test/java/com/coderstower/socialmediapubisher/springpublisher/main/controller/PostsControllerTest.java @@ -38,7 +38,7 @@ public void ping(){ @Test public void postNext() throws MalformedURLException { - when(postPublisher.publishNext()).thenReturn(List.of(Post.builder() + when(postPublisher.publishNext(group)).thenReturn(List.of(Post.builder() .id("2") .name("My Post 2") .description("My second post") From 61151504eefec1c2b29460ff0f2887c2c64619ee Mon Sep 17 00:00:00 2001 From: Daniel Pelaez Date: Sun, 7 Apr 2024 18:49:29 -0500 Subject: [PATCH 09/13] Adding group field to publish posts by group --- .../abstraction/post/PostPublisherTest.java | 21 ++++++++++--------- .../main/controller/PostsControllerTest.java | 14 +++++++------ 2 files changed, 19 insertions(+), 16 deletions(-) diff --git a/spring-publisher/src/test/java/com/coderstower/socialmediapubisher/springpublisher/abstraction/post/PostPublisherTest.java b/spring-publisher/src/test/java/com/coderstower/socialmediapubisher/springpublisher/abstraction/post/PostPublisherTest.java index 0a9649e..a13faf5 100644 --- a/spring-publisher/src/test/java/com/coderstower/socialmediapubisher/springpublisher/abstraction/post/PostPublisherTest.java +++ b/spring-publisher/src/test/java/com/coderstower/socialmediapubisher/springpublisher/abstraction/post/PostPublisherTest.java @@ -18,6 +18,7 @@ import java.time.ZoneId; import java.time.ZonedDateTime; import java.util.List; +import java.util.Optional; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertThrows; @@ -36,7 +37,7 @@ class PostPublisherTest { @BeforeEach public void before() { this.postPublisher = new PostPublisher(List.of(socialMediaPublisher1, socialMediaPublisher2), postRepository, Clock - .fixed(ZonedDateTime.of(2020, 3, 3, 5, 6, 8, 1, ZoneId.of("UTC")).toInstant(), ZoneId.of("UTC")), List.of("group1")); + .fixed(ZonedDateTime.of(2020, 3, 3, 5, 6, 8, 1, ZoneId.of("UTC")).toInstant(), ZoneId.of("UTC"))); } @Test @@ -47,7 +48,7 @@ public void publishNext_pingFailed_exception() { .status(Acknowledge.Status.FAILURE).build()); when(socialMediaPublisher2.getName()).thenReturn("LINKEDIN"); - IllegalStateException exception = assertThrows(IllegalStateException.class, () -> postPublisher.publishNext(group)); + IllegalStateException exception = assertThrows(IllegalStateException.class, () -> postPublisher.publishNext("group1")); assertThat(exception.getMessage()).isEqualTo("Ping to LINKEDIN failed: " + Acknowledge.builder() .status(Acknowledge.Status.FAILURE).build()); @@ -55,13 +56,13 @@ public void publishNext_pingFailed_exception() { @Test public void publishNext_noPost_exception() { - when(postRepository.findAll()).thenReturn(List.of()); + when(postRepository.getNextToPublish("group1")).thenReturn(Optional.empty()); when(socialMediaPublisher1.ping()).thenReturn(Acknowledge.builder() .status(Acknowledge.Status.SUCCESS).build()); when(socialMediaPublisher2.ping()).thenReturn(Acknowledge.builder() .status(Acknowledge.Status.SUCCESS).build()); - IllegalStateException exception = assertThrows(IllegalStateException.class, () -> postPublisher.publishNext(group)); + IllegalStateException exception = assertThrows(IllegalStateException.class, () -> postPublisher.publishNext("group1")); assertThat(exception.getMessage()).isEqualTo("There is not next post to publish"); } @@ -85,7 +86,6 @@ public void publishNext_publishFailed_exception() throws MalformedURLException { .publishedDate(LocalDateTime.of(2020, 2, 3, 5, 6, 8, 1)) .tags(List.of("tag1", "tag2")) .url(URI.create("https://myblog/post").toURL()) - .group("group1") .publications(List .of(Publication.builder() .id("id") @@ -98,9 +98,10 @@ public void publishNext_publishFailed_exception() throws MalformedURLException { .status(Publication.Status.FAILURE) .publisher("LINKEDIN") .build())) + .group("group1") .build(); - when(postRepository.findAll()).thenReturn(List.of(post)); + when(postRepository.getNextToPublish("group1")).thenReturn(Optional.of(post)); when(socialMediaPublisher1.ping()).thenReturn(Acknowledge.builder() .status(Acknowledge.Status.SUCCESS).build()); when(socialMediaPublisher1.publish(post)).thenReturn(Publication.builder() @@ -117,7 +118,7 @@ public void publishNext_publishFailed_exception() throws MalformedURLException { .publisher("LINKEDIN") .build()); - IllegalStateException exception = assertThrows(IllegalStateException.class, () -> postPublisher.publishNext(group)); + IllegalStateException exception = assertThrows(IllegalStateException.class, () -> postPublisher.publishNext("group1")); assertThat(exception.getMessage()).isEqualTo("Error publishing the post: " + expectedPost); } @@ -167,7 +168,7 @@ public void publishNext_publishSuccess_publications() throws MalformedURLExcepti .build())) .build(); - when(postRepository.findAll()).thenReturn(List.of(post)); + when(postRepository.getNextToPublish("group1")).thenReturn(Optional.of(post)); when(socialMediaPublisher1.ping()).thenReturn(Acknowledge.builder() .status(Acknowledge.Status.SUCCESS).build()); when(socialMediaPublisher1.publish(post)).thenReturn(Publication.builder() @@ -186,9 +187,9 @@ public void publishNext_publishSuccess_publications() throws MalformedURLExcepti .build()); when(postRepository.update(postUpdated)).thenReturn(postUpdated); - List publishedPost = postPublisher.publishNext(group); + Post publishedPost = postPublisher.publishNext("group1"); - assertThat(publishedPost).isEqualTo(List.of(expectedPost)); + assertThat(publishedPost).isEqualTo(expectedPost); } } \ No newline at end of file diff --git a/spring-publisher/src/test/java/com/coderstower/socialmediapubisher/springpublisher/main/controller/PostsControllerTest.java b/spring-publisher/src/test/java/com/coderstower/socialmediapubisher/springpublisher/main/controller/PostsControllerTest.java index 64e3425..d96ab8c 100644 --- a/spring-publisher/src/test/java/com/coderstower/socialmediapubisher/springpublisher/main/controller/PostsControllerTest.java +++ b/spring-publisher/src/test/java/com/coderstower/socialmediapubisher/springpublisher/main/controller/PostsControllerTest.java @@ -27,7 +27,7 @@ class PostsControllerTest { private PostsController postsController; @Test - public void ping(){ + public void ping() { Map result = postsController.ping(); Map pong = new HashMap<>(); @@ -38,7 +38,7 @@ public void ping(){ @Test public void postNext() throws MalformedURLException { - when(postPublisher.publishNext(group)).thenReturn(List.of(Post.builder() + when(postPublisher.publishNext("group1")).thenReturn(Post.builder() .id("2") .name("My Post 2") .description("My second post") @@ -49,11 +49,12 @@ public void postNext() throws MalformedURLException { .status(Publication.Status.FAILURE) .publisher("twitter") .build())) - .build())); + .group("group1") + .build()); - List result = postsController.postNext(); + Post result = postsController.postNext("group1"); - assertThat(result).isEqualTo(List.of(Post.builder() + assertThat(result).isEqualTo(Post.builder() .id("2") .name("My Post 2") .description("My second post") @@ -64,7 +65,8 @@ public void postNext() throws MalformedURLException { .status(Publication.Status.FAILURE) .publisher("twitter") .build())) - .build())); + .group("group1") + .build()); } } \ No newline at end of file From 317f988cbf23893c1f4548bb356ba831dc63b5b0 Mon Sep 17 00:00:00 2001 From: Daniel Pelaez Date: Sun, 7 Apr 2024 18:57:46 -0500 Subject: [PATCH 10/13] Adding group field to publish posts by group --- .../src/main/resources/application.yml | 2 -- ...ckSocialMediaCredentialsHandlingTests.java | 2 +- .../aws/MockSocialMediaSuccessfulTests.java | 2 +- .../post/PostAWSRepositoryTest.java | 29 +++++++------------ 4 files changed, 12 insertions(+), 23 deletions(-) diff --git a/aws-publisher/src/main/resources/application.yml b/aws-publisher/src/main/resources/application.yml index 03031d2..2f70249 100644 --- a/aws-publisher/src/main/resources/application.yml +++ b/aws-publisher/src/main/resources/application.yml @@ -5,8 +5,6 @@ # root: WARN social-media-publisher: - groups: - - group1 credentials: login-host: 'http://localhost:8080' login-url: '${social-media-publisher.credentials.login-host}/oauth2/{social-media-id}/credentials' diff --git a/aws-publisher/src/test/java/com/coderstower/socialmediapubisher/springpublisher/main/aws/MockSocialMediaCredentialsHandlingTests.java b/aws-publisher/src/test/java/com/coderstower/socialmediapubisher/springpublisher/main/aws/MockSocialMediaCredentialsHandlingTests.java index 519a7ca..7b29606 100644 --- a/aws-publisher/src/test/java/com/coderstower/socialmediapubisher/springpublisher/main/aws/MockSocialMediaCredentialsHandlingTests.java +++ b/aws-publisher/src/test/java/com/coderstower/socialmediapubisher/springpublisher/main/aws/MockSocialMediaCredentialsHandlingTests.java @@ -83,7 +83,7 @@ class MockSocialMediaCredentialsHandlingTests { void publish_credentialsExpired_unauthorizedException() throws Exception { mockingTwitter(); - mvc.perform(post("/posts/next") + mvc.perform(post("/posts/group1/next") .with(csrf()) .contentType(MediaType.APPLICATION_JSON)) .andExpect(status().isUnauthorized()) diff --git a/aws-publisher/src/test/java/com/coderstower/socialmediapubisher/springpublisher/main/aws/MockSocialMediaSuccessfulTests.java b/aws-publisher/src/test/java/com/coderstower/socialmediapubisher/springpublisher/main/aws/MockSocialMediaSuccessfulTests.java index 6ed735c..a717cf9 100644 --- a/aws-publisher/src/test/java/com/coderstower/socialmediapubisher/springpublisher/main/aws/MockSocialMediaSuccessfulTests.java +++ b/aws-publisher/src/test/java/com/coderstower/socialmediapubisher/springpublisher/main/aws/MockSocialMediaSuccessfulTests.java @@ -78,7 +78,7 @@ void publish_allSocialMedia_success() throws Exception { mockingTwitter(); mockingLinkedIn(); - mvc.perform(post("/posts/next") + mvc.perform(post("/posts/group1/next") .with(csrf()) .contentType(MediaType.APPLICATION_JSON)) .andExpect(status().isOk()) diff --git a/aws-publisher/src/test/java/com/coderstower/socialmediapubisher/springpublisher/main/aws/repository/post/PostAWSRepositoryTest.java b/aws-publisher/src/test/java/com/coderstower/socialmediapubisher/springpublisher/main/aws/repository/post/PostAWSRepositoryTest.java index 48a5154..6a33102 100644 --- a/aws-publisher/src/test/java/com/coderstower/socialmediapubisher/springpublisher/main/aws/repository/post/PostAWSRepositoryTest.java +++ b/aws-publisher/src/test/java/com/coderstower/socialmediapubisher/springpublisher/main/aws/repository/post/PostAWSRepositoryTest.java @@ -43,26 +43,17 @@ public void getNextToPublish() throws MalformedURLException { .publishedDate(LocalDateTime.parse("2013-09-17T18:47:52")) .build())); - List post = postAWSRepository.findAll(); + Optional post = postAWSRepository.getNextToPublish("group1"); - assertThat(post).isEqualTo(List.of(Post.builder() - .id("2") - .name("My Post 2") - .description("My second post") - .tags(List.of("tag1", "tag2")) - .group("group1") - .url(URI.create("https://coderstower.com/2020/01/13/open-close-principle-by-example/").toURL()) - .publishedDate(LocalDateTime.parse("2012-09-17T18:47:52")) - .build(), - Post.builder() - .id("1") - .name("My Post 1") - .description("My first post") - .tags(List.of("tag1", "tag2")) - .group("group1") - .url(URI.create("https://coderstower.com/2020/02/18/unit-tests-vs-integration-tests/").toURL()) - .publishedDate(LocalDateTime.parse("2013-09-17T18:47:52")) - .build())); + assertThat(post).isEqualTo(Optional.of(Post.builder() + .id("2") + .name("My Post 2") + .description("My second post") + .tags(List.of("tag1", "tag2")) + .url(URI.create("https://coderstower.com/2020/01/13/open-close-principle-by-example/").toURL()) + .publishedDate(LocalDateTime.parse("2012-09-17T18:47:52")) + .group("group1") + .build())); } @Test From 10a4a50741daa4b265f4316865e30f9e04ef0a0c Mon Sep 17 00:00:00 2001 From: Daniel Pelaez Date: Mon, 8 Apr 2024 18:16:00 -0500 Subject: [PATCH 11/13] Adding group field to publish posts by group --- .../src/main/resources/application-secure.yml | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/aws-publisher/src/main/resources/application-secure.yml b/aws-publisher/src/main/resources/application-secure.yml index af1fcfd..148018a 100644 --- a/aws-publisher/src/main/resources/application-secure.yml +++ b/aws-publisher/src/main/resources/application-secure.yml @@ -2,6 +2,11 @@ social-media-publisher: principal-names-allowed: linkedin: xxx +amazon: + dynamodb: + accesskey: xxx + secretkey: xxx + spring: security: oauth2: @@ -14,12 +19,14 @@ spring: authorization-grant-type: authorization_code redirect-uri: '{baseUrl}/login/oauth2/code/{registrationId}' scope: - - r_liteprofile - - r_emailaddress + - openid + - profile + - email - w_member_social provider: linkedin: authorization-uri: https://www.linkedin.com/oauth/v2/authorization token-uri: https://www.linkedin.com/oauth/v2/accessToken - user-info-uri: https://api.linkedin.com/v2/me - user-name-attribute: id \ No newline at end of file + user-info-uri: https://api.linkedin.com/v2/userinfo + user-name-attribute: id + jwk-set-uri: https://www.linkedin.com/oauth/openid/jwks \ No newline at end of file From ab359b018f36fdd2dbd7d5853f9f50274a69965f Mon Sep 17 00:00:00 2001 From: Daniel Pelaez Date: Tue, 9 Apr 2024 16:39:36 -0500 Subject: [PATCH 12/13] Adding group field to publish posts by group --- .../aws/MockSocialMediaSuccessfulTests.java | 10 ++--- ...{ShareContent.java => ArticleContent.java} | 9 ++-- .../main/socialmedia/linkedin/Content.java | 10 +++++ .../socialmedia/linkedin/Distribution.java | 10 +++++ .../linkedin/LinkedInPublisher.java | 45 ++++++++++--------- .../socialmedia/linkedin/LinkedInShare.java | 6 ++- .../main/socialmedia/linkedin/Profile.java | 2 +- .../socialmedia/linkedin/SpecificContent.java | 12 ----- .../main/socialmedia/linkedin/Visibility.java | 12 ----- .../linkedin/LinkedInPublisherTest.java | 18 ++++---- 10 files changed, 66 insertions(+), 68 deletions(-) rename spring-publisher/src/main/java/com/coderstower/socialmediapubisher/springpublisher/main/socialmedia/linkedin/{ShareContent.java => ArticleContent.java} (53%) create mode 100644 spring-publisher/src/main/java/com/coderstower/socialmediapubisher/springpublisher/main/socialmedia/linkedin/Content.java create mode 100644 spring-publisher/src/main/java/com/coderstower/socialmediapubisher/springpublisher/main/socialmedia/linkedin/Distribution.java delete mode 100644 spring-publisher/src/main/java/com/coderstower/socialmediapubisher/springpublisher/main/socialmedia/linkedin/SpecificContent.java delete mode 100644 spring-publisher/src/main/java/com/coderstower/socialmediapubisher/springpublisher/main/socialmedia/linkedin/Visibility.java diff --git a/aws-publisher/src/test/java/com/coderstower/socialmediapubisher/springpublisher/main/aws/MockSocialMediaSuccessfulTests.java b/aws-publisher/src/test/java/com/coderstower/socialmediapubisher/springpublisher/main/aws/MockSocialMediaSuccessfulTests.java index a717cf9..4d01c80 100644 --- a/aws-publisher/src/test/java/com/coderstower/socialmediapubisher/springpublisher/main/aws/MockSocialMediaSuccessfulTests.java +++ b/aws-publisher/src/test/java/com/coderstower/socialmediapubisher/springpublisher/main/aws/MockSocialMediaSuccessfulTests.java @@ -14,8 +14,8 @@ import com.coderstower.socialmediapubisher.springpublisher.main.socialmedia.linkedin.LinkedInShare; import com.coderstower.socialmediapubisher.springpublisher.main.socialmedia.linkedin.Media; import com.coderstower.socialmediapubisher.springpublisher.main.socialmedia.linkedin.Profile; -import com.coderstower.socialmediapubisher.springpublisher.main.socialmedia.linkedin.ShareContent; -import com.coderstower.socialmediapubisher.springpublisher.main.socialmedia.linkedin.SpecificContent; +import com.coderstower.socialmediapubisher.springpublisher.main.socialmedia.linkedin.ArticleContent; +import com.coderstower.socialmediapubisher.springpublisher.main.socialmedia.linkedin.Content; import com.coderstower.socialmediapubisher.springpublisher.main.socialmedia.linkedin.Text; import com.coderstower.socialmediapubisher.springpublisher.main.socialmedia.linkedin.Visibility; import org.junit.jupiter.api.Test; @@ -96,14 +96,14 @@ private void mockingLinkedIn() { when(restTemplate.exchange("https://api.linkedin.com/v2/me", HttpMethod.GET, requestMe, Profile.class)) .thenReturn(ResponseEntity.ok(Profile.builder() - .id("memberid") + .sub("memberid") .build())); LinkedInShare linkedInShare = LinkedInShare.builder() .author("urn:li:person:memberid") .lifecycleState("PUBLISHED") - .specificContent(SpecificContent.builder() - .shareContent(ShareContent.builder() + .content(Content.builder() + .article(ArticleContent.builder() .shareCommentary(Text.builder() .text("My second post\n\n#tag1 #tag2") .build()) diff --git a/spring-publisher/src/main/java/com/coderstower/socialmediapubisher/springpublisher/main/socialmedia/linkedin/ShareContent.java b/spring-publisher/src/main/java/com/coderstower/socialmediapubisher/springpublisher/main/socialmedia/linkedin/ArticleContent.java similarity index 53% rename from spring-publisher/src/main/java/com/coderstower/socialmediapubisher/springpublisher/main/socialmedia/linkedin/ShareContent.java rename to spring-publisher/src/main/java/com/coderstower/socialmediapubisher/springpublisher/main/socialmedia/linkedin/ArticleContent.java index a26220c..ef2f0e6 100644 --- a/spring-publisher/src/main/java/com/coderstower/socialmediapubisher/springpublisher/main/socialmedia/linkedin/ShareContent.java +++ b/spring-publisher/src/main/java/com/coderstower/socialmediapubisher/springpublisher/main/socialmedia/linkedin/ArticleContent.java @@ -8,9 +8,8 @@ @Data @Builder -public class ShareContent { - private final Text shareCommentary; - private final String shareMediaCategory; - @Singular("media") - private final List media; +public class ArticleContent { + private final String title; + private final String description; + private final String source; } diff --git a/spring-publisher/src/main/java/com/coderstower/socialmediapubisher/springpublisher/main/socialmedia/linkedin/Content.java b/spring-publisher/src/main/java/com/coderstower/socialmediapubisher/springpublisher/main/socialmedia/linkedin/Content.java new file mode 100644 index 0000000..cfa8965 --- /dev/null +++ b/spring-publisher/src/main/java/com/coderstower/socialmediapubisher/springpublisher/main/socialmedia/linkedin/Content.java @@ -0,0 +1,10 @@ +package com.coderstower.socialmediapubisher.springpublisher.main.socialmedia.linkedin; + +import lombok.Builder; +import lombok.Data; + +@Data +@Builder +public class Content { + private final ArticleContent article; +} diff --git a/spring-publisher/src/main/java/com/coderstower/socialmediapubisher/springpublisher/main/socialmedia/linkedin/Distribution.java b/spring-publisher/src/main/java/com/coderstower/socialmediapubisher/springpublisher/main/socialmedia/linkedin/Distribution.java new file mode 100644 index 0000000..597be90 --- /dev/null +++ b/spring-publisher/src/main/java/com/coderstower/socialmediapubisher/springpublisher/main/socialmedia/linkedin/Distribution.java @@ -0,0 +1,10 @@ +package com.coderstower.socialmediapubisher.springpublisher.main.socialmedia.linkedin; + +import lombok.Builder; +import lombok.Data; + +@Data +@Builder +public class Distribution { + private final String feedDistribution; +} diff --git a/spring-publisher/src/main/java/com/coderstower/socialmediapubisher/springpublisher/main/socialmedia/linkedin/LinkedInPublisher.java b/spring-publisher/src/main/java/com/coderstower/socialmediapubisher/springpublisher/main/socialmedia/linkedin/LinkedInPublisher.java index df1f913..439789e 100644 --- a/spring-publisher/src/main/java/com/coderstower/socialmediapubisher/springpublisher/main/socialmedia/linkedin/LinkedInPublisher.java +++ b/spring-publisher/src/main/java/com/coderstower/socialmediapubisher/springpublisher/main/socialmedia/linkedin/LinkedInPublisher.java @@ -13,6 +13,7 @@ import org.springframework.http.HttpMethod; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; +import org.springframework.web.client.HttpClientErrorException; import org.springframework.web.client.RestTemplate; import org.springframework.web.util.UriTemplate; @@ -64,29 +65,18 @@ public Publication publish(Post post) { Profile profile = getProfile(credentials); LinkedInShare linkedInShare = LinkedInShare.builder() - .author("urn:li:person:" + profile.getId()) + .author("urn:li:person:" + profile.getSub()) + .commentary(post.getDescription()) + .distribution(Distribution.builder().feedDistribution("MAIN_FEED").build()) .lifecycleState("PUBLISHED") - .specificContent(SpecificContent.builder() - .shareContent(ShareContent.builder() - .shareCommentary(Text.builder() - .text(post.basicFormatWithoutURL()) - .build()) - .shareMediaCategory("ARTICLE") - .media(Media.builder() - .description(Text.builder() - .text(post.getDescription()) - .build()) - .title(Text.builder() - .text(post.getName()) - .build()) - .status("READY") - .originalUrl(post.getUrl().toString()) - .build()) + .content(Content.builder() + .article(ArticleContent.builder() + .description(post.getDescription()) + .title(post.getName()) + .source(post.getUrl().toString()) .build()) .build()) - .visibility(Visibility.builder() - .memberNetworkVisibility("PUBLIC") - .build()) + .visibility("PUBLIC") .build(); String shareId = publish(linkedInShare, credentials); @@ -105,6 +95,15 @@ public Publication publish(Post post) { .publishedDate(LocalDateTime.now(clock)) .build(); } + } catch (HttpClientErrorException e) { + log.error("Error publishing to " + name + ", response body: " + e.getResponseBodyAsString(), e); + + return Publication.builder() + .status(Publication.Status.FAILURE) + .publisher(name) + .publishedDate(LocalDateTime.now(clock)) + .build(); + } catch (Exception e) { log.error("Error publishing to " + name, e); @@ -120,11 +119,12 @@ private String publish(LinkedInShare linkedInShare, OAuth2Credentials credential HttpHeaders httpHeaders = new HttpHeaders(); httpHeaders.setContentType(MediaType.APPLICATION_JSON); httpHeaders.add("X-Restli-Protocol-Version", "2.0.0"); + httpHeaders.add("LinkedIn-Version", "202304"); httpHeaders.setBearerAuth(credentials.getAccessToken()); HttpEntity requestEntity = new HttpEntity<>(linkedInShare, httpHeaders); - ResponseEntity response = restTemplate.exchange("https://api.linkedin.com/v2/ugcPosts", HttpMethod.POST, requestEntity, Void.class); + ResponseEntity response = restTemplate.exchange("https://api.linkedin.com/rest/posts", HttpMethod.POST, requestEntity, Void.class); if (!response.getStatusCode().is2xxSuccessful()) { throw new IllegalStateException("Problem trying to share a linkedin post: " + response.getStatusCode()); @@ -137,11 +137,12 @@ private Profile getProfile(OAuth2Credentials credentials) { HttpHeaders httpHeaders = new HttpHeaders(); httpHeaders.setContentType(MediaType.APPLICATION_JSON); httpHeaders.add("X-Restli-Protocol-Version", "2.0.0"); + httpHeaders.add("LinkedIn-Version", "202304"); httpHeaders.setBearerAuth(credentials.getAccessToken()); HttpEntity requestEntity = new HttpEntity<>(httpHeaders); - ResponseEntity response = restTemplate.exchange("https://api.linkedin.com/v2/me", HttpMethod.GET, requestEntity, Profile.class); + ResponseEntity response = restTemplate.exchange("https://api.linkedin.com/v2/userinfo", HttpMethod.GET, requestEntity, Profile.class); if (!response.getStatusCode().is2xxSuccessful()) { throw new IllegalStateException("Problem trying to get the profile: " + response.getStatusCode()); diff --git a/spring-publisher/src/main/java/com/coderstower/socialmediapubisher/springpublisher/main/socialmedia/linkedin/LinkedInShare.java b/spring-publisher/src/main/java/com/coderstower/socialmediapubisher/springpublisher/main/socialmedia/linkedin/LinkedInShare.java index d337f52..4cbd39a 100644 --- a/spring-publisher/src/main/java/com/coderstower/socialmediapubisher/springpublisher/main/socialmedia/linkedin/LinkedInShare.java +++ b/spring-publisher/src/main/java/com/coderstower/socialmediapubisher/springpublisher/main/socialmedia/linkedin/LinkedInShare.java @@ -6,8 +6,10 @@ @Data @Builder public class LinkedInShare { + private final String commentary; + private final Distribution distribution; private final String author; private final String lifecycleState; - private final SpecificContent specificContent; - private final Visibility visibility; + private final Content content; + private final String visibility; } diff --git a/spring-publisher/src/main/java/com/coderstower/socialmediapubisher/springpublisher/main/socialmedia/linkedin/Profile.java b/spring-publisher/src/main/java/com/coderstower/socialmediapubisher/springpublisher/main/socialmedia/linkedin/Profile.java index 789e350..9282df0 100644 --- a/spring-publisher/src/main/java/com/coderstower/socialmediapubisher/springpublisher/main/socialmedia/linkedin/Profile.java +++ b/spring-publisher/src/main/java/com/coderstower/socialmediapubisher/springpublisher/main/socialmedia/linkedin/Profile.java @@ -10,5 +10,5 @@ @NoArgsConstructor @AllArgsConstructor public class Profile { - private String id; + private String sub; } diff --git a/spring-publisher/src/main/java/com/coderstower/socialmediapubisher/springpublisher/main/socialmedia/linkedin/SpecificContent.java b/spring-publisher/src/main/java/com/coderstower/socialmediapubisher/springpublisher/main/socialmedia/linkedin/SpecificContent.java deleted file mode 100644 index 33163f3..0000000 --- a/spring-publisher/src/main/java/com/coderstower/socialmediapubisher/springpublisher/main/socialmedia/linkedin/SpecificContent.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.coderstower.socialmediapubisher.springpublisher.main.socialmedia.linkedin; - -import com.fasterxml.jackson.annotation.JsonProperty; -import lombok.Builder; -import lombok.Data; - -@Data -@Builder -public class SpecificContent { - @JsonProperty("com.linkedin.ugc.ShareContent") - private final ShareContent shareContent; -} diff --git a/spring-publisher/src/main/java/com/coderstower/socialmediapubisher/springpublisher/main/socialmedia/linkedin/Visibility.java b/spring-publisher/src/main/java/com/coderstower/socialmediapubisher/springpublisher/main/socialmedia/linkedin/Visibility.java deleted file mode 100644 index 39514d7..0000000 --- a/spring-publisher/src/main/java/com/coderstower/socialmediapubisher/springpublisher/main/socialmedia/linkedin/Visibility.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.coderstower.socialmediapubisher.springpublisher.main.socialmedia.linkedin; - -import com.fasterxml.jackson.annotation.JsonProperty; -import lombok.Builder; -import lombok.Data; - -@Data -@Builder -public class Visibility { - @JsonProperty("com.linkedin.ugc.MemberNetworkVisibility") - private final String memberNetworkVisibility; -} diff --git a/spring-publisher/src/test/java/com/coderstower/socialmediapubisher/springpublisher/main/socialmedia/linkedin/LinkedInPublisherTest.java b/spring-publisher/src/test/java/com/coderstower/socialmediapubisher/springpublisher/main/socialmedia/linkedin/LinkedInPublisherTest.java index 871c0b4..b21e4f3 100644 --- a/spring-publisher/src/test/java/com/coderstower/socialmediapubisher/springpublisher/main/socialmedia/linkedin/LinkedInPublisherTest.java +++ b/spring-publisher/src/test/java/com/coderstower/socialmediapubisher/springpublisher/main/socialmedia/linkedin/LinkedInPublisherTest.java @@ -121,14 +121,14 @@ public void publish_noShare_publicationError() throws MalformedURLException { when(restTemplate.exchange("https://api.linkedin.com/v2/me", HttpMethod.GET, requestEntityProfile, Profile.class)) .thenReturn(ResponseEntity.ok(Profile.builder() - .id("memberid") + .sub("memberid") .build())); LinkedInShare linkedInShare = LinkedInShare.builder() .author("urn:li:person:memberid") .lifecycleState("PUBLISHED") - .specificContent(SpecificContent.builder() - .shareContent(ShareContent.builder() + .content(Content.builder() + .article(ArticleContent.builder() .shareCommentary(Text.builder() .text("My second post\n\n#tag1 #tag2") .build()) @@ -186,14 +186,14 @@ public void publish_noShareId_publicationError() throws MalformedURLException { when(restTemplate.exchange("https://api.linkedin.com/v2/me", HttpMethod.GET, requestEntityProfile, Profile.class)) .thenReturn(ResponseEntity.ok(Profile.builder() - .id("memberid") + .sub("memberid") .build())); LinkedInShare linkedInShare = LinkedInShare.builder() .author("urn:li:person:memberid") .lifecycleState("PUBLISHED") - .specificContent(SpecificContent.builder() - .shareContent(ShareContent.builder() + .content(Content.builder() + .article(ArticleContent.builder() .shareCommentary(Text.builder() .text("My second post\n\n#tag1 #tag2") .build()) @@ -251,14 +251,14 @@ public void publish_shareId_publicationSucced() throws MalformedURLException { when(restTemplate.exchange("https://api.linkedin.com/v2/me", HttpMethod.GET, requestEntityProfile, Profile.class)) .thenReturn(ResponseEntity.ok(Profile.builder() - .id("memberid") + .sub("memberid") .build())); LinkedInShare linkedInShare = LinkedInShare.builder() .author("urn:li:person:memberid") .lifecycleState("PUBLISHED") - .specificContent(SpecificContent.builder() - .shareContent(ShareContent.builder() + .content(Content.builder() + .article(ArticleContent.builder() .shareCommentary(Text.builder() .text("My second post\n\n#tag1 #tag2") .build()) From c0c13fd70d859f79ebf97b1a2c983de4349bbc74 Mon Sep 17 00:00:00 2001 From: Daniel Pelaez Date: Wed, 10 Apr 2024 08:43:38 -0500 Subject: [PATCH 13/13] Adding group field to publish posts by group --- .../aws/MockSocialMediaSuccessfulTests.java | 37 +++------ .../linkedin/LinkedInPublisher.java | 2 +- .../linkedin/LinkedInPublisherTest.java | 77 ++++++------------- 3 files changed, 36 insertions(+), 80 deletions(-) diff --git a/aws-publisher/src/test/java/com/coderstower/socialmediapubisher/springpublisher/main/aws/MockSocialMediaSuccessfulTests.java b/aws-publisher/src/test/java/com/coderstower/socialmediapubisher/springpublisher/main/aws/MockSocialMediaSuccessfulTests.java index 4d01c80..3209f79 100644 --- a/aws-publisher/src/test/java/com/coderstower/socialmediapubisher/springpublisher/main/aws/MockSocialMediaSuccessfulTests.java +++ b/aws-publisher/src/test/java/com/coderstower/socialmediapubisher/springpublisher/main/aws/MockSocialMediaSuccessfulTests.java @@ -11,13 +11,7 @@ import com.amazonaws.services.dynamodbv2.model.ProvisionedThroughput; import com.amazonaws.services.dynamodbv2.model.PutItemRequest; import com.amazonaws.services.dynamodbv2.model.ScalarAttributeType; -import com.coderstower.socialmediapubisher.springpublisher.main.socialmedia.linkedin.LinkedInShare; -import com.coderstower.socialmediapubisher.springpublisher.main.socialmedia.linkedin.Media; -import com.coderstower.socialmediapubisher.springpublisher.main.socialmedia.linkedin.Profile; -import com.coderstower.socialmediapubisher.springpublisher.main.socialmedia.linkedin.ArticleContent; -import com.coderstower.socialmediapubisher.springpublisher.main.socialmedia.linkedin.Content; -import com.coderstower.socialmediapubisher.springpublisher.main.socialmedia.linkedin.Text; -import com.coderstower.socialmediapubisher.springpublisher.main.socialmedia.linkedin.Visibility; +import com.coderstower.socialmediapubisher.springpublisher.main.socialmedia.linkedin.*; import org.junit.jupiter.api.Test; import org.junitpioneer.jupiter.SetSystemProperty; import org.springframework.beans.factory.annotation.Autowired; @@ -90,11 +84,12 @@ private void mockingLinkedIn() { HttpHeaders httpHeaders = new HttpHeaders(); httpHeaders.setContentType(MediaType.APPLICATION_JSON); httpHeaders.add("X-Restli-Protocol-Version", "2.0.0"); + httpHeaders.add("LinkedIn-Version", "202304"); httpHeaders.setBearerAuth("access123"); HttpEntity requestMe = new HttpEntity<>(httpHeaders); - when(restTemplate.exchange("https://api.linkedin.com/v2/me", HttpMethod.GET, requestMe, Profile.class)) + when(restTemplate.exchange("https://api.linkedin.com/v2/userinfo", HttpMethod.GET, requestMe, Profile.class)) .thenReturn(ResponseEntity.ok(Profile.builder() .sub("memberid") .build())); @@ -102,32 +97,22 @@ private void mockingLinkedIn() { LinkedInShare linkedInShare = LinkedInShare.builder() .author("urn:li:person:memberid") .lifecycleState("PUBLISHED") + .commentary("My second post\n\n#tag1 #tag2") + .distribution(Distribution.builder().feedDistribution("MAIN_FEED").build()) + .lifecycleState("PUBLISHED") .content(Content.builder() .article(ArticleContent.builder() - .shareCommentary(Text.builder() - .text("My second post\n\n#tag1 #tag2") - .build()) - .shareMediaCategory("ARTICLE") - .media(Media.builder() - .description(Text.builder() - .text("My second post") - .build()) - .title(Text.builder() - .text("My Post 2") - .build()) - .status("READY") - .originalUrl("https://coderstower.com/2020/01/13/open-close-principle-by-example/") - .build()) + .description("My second post") + .title("My Post 2") + .source("https://coderstower.com/2020/01/13/open-close-principle-by-example/") .build()) .build()) - .visibility(Visibility.builder() - .memberNetworkVisibility("PUBLIC") - .build()) + .visibility("PUBLIC") .build(); HttpEntity requestShare = new HttpEntity<>(linkedInShare, httpHeaders); - when(restTemplate.exchange("https://api.linkedin.com/v2/ugcPosts", HttpMethod.POST, requestShare, Void.class)) + when(restTemplate.exchange("https://api.linkedin.com/rest/posts", HttpMethod.POST, requestShare, Void.class)) .thenReturn(ResponseEntity.ok() .header("X-RestLi-Id", "shareid") .build()); diff --git a/spring-publisher/src/main/java/com/coderstower/socialmediapubisher/springpublisher/main/socialmedia/linkedin/LinkedInPublisher.java b/spring-publisher/src/main/java/com/coderstower/socialmediapubisher/springpublisher/main/socialmedia/linkedin/LinkedInPublisher.java index 439789e..3b3719d 100644 --- a/spring-publisher/src/main/java/com/coderstower/socialmediapubisher/springpublisher/main/socialmedia/linkedin/LinkedInPublisher.java +++ b/spring-publisher/src/main/java/com/coderstower/socialmediapubisher/springpublisher/main/socialmedia/linkedin/LinkedInPublisher.java @@ -66,7 +66,7 @@ public Publication publish(Post post) { LinkedInShare linkedInShare = LinkedInShare.builder() .author("urn:li:person:" + profile.getSub()) - .commentary(post.getDescription()) + .commentary(post.basicFormatWithoutURL()) .distribution(Distribution.builder().feedDistribution("MAIN_FEED").build()) .lifecycleState("PUBLISHED") .content(Content.builder() diff --git a/spring-publisher/src/test/java/com/coderstower/socialmediapubisher/springpublisher/main/socialmedia/linkedin/LinkedInPublisherTest.java b/spring-publisher/src/test/java/com/coderstower/socialmediapubisher/springpublisher/main/socialmedia/linkedin/LinkedInPublisherTest.java index b21e4f3..70440e4 100644 --- a/spring-publisher/src/test/java/com/coderstower/socialmediapubisher/springpublisher/main/socialmedia/linkedin/LinkedInPublisherTest.java +++ b/spring-publisher/src/test/java/com/coderstower/socialmediapubisher/springpublisher/main/socialmedia/linkedin/LinkedInPublisherTest.java @@ -127,27 +127,17 @@ public void publish_noShare_publicationError() throws MalformedURLException { LinkedInShare linkedInShare = LinkedInShare.builder() .author("urn:li:person:memberid") .lifecycleState("PUBLISHED") + .commentary("commentary") + .distribution(Distribution.builder().feedDistribution("MAIN_FEED").build()) + .lifecycleState("PUBLISHED") .content(Content.builder() .article(ArticleContent.builder() - .shareCommentary(Text.builder() - .text("My second post\n\n#tag1 #tag2") - .build()) - .shareMediaCategory("ARTICLE") - .media(Media.builder() - .description(Text.builder() - .text("My second post") - .build()) - .title(Text.builder() - .text("My Post 2") - .build()) - .status("READY") - .originalUrl("https://coderstower.com/2020/01/13/open-close-principle-by-example/") - .build()) + .description("My second post\n\n#tag1 #tag2") + .title("My second post") + .source("https://coderstower.com/2020/01/13/open-close-principle-by-example/") .build()) .build()) - .visibility(Visibility.builder() - .memberNetworkVisibility("PUBLIC") - .build()) + .visibility("PUBLIC") .build(); HttpEntity requestShare = new HttpEntity<>(linkedInShare, httpHeaders); @@ -192,27 +182,17 @@ public void publish_noShareId_publicationError() throws MalformedURLException { LinkedInShare linkedInShare = LinkedInShare.builder() .author("urn:li:person:memberid") .lifecycleState("PUBLISHED") + .commentary("commentary") + .distribution(Distribution.builder().feedDistribution("MAIN_FEED").build()) + .lifecycleState("PUBLISHED") .content(Content.builder() .article(ArticleContent.builder() - .shareCommentary(Text.builder() - .text("My second post\n\n#tag1 #tag2") - .build()) - .shareMediaCategory("ARTICLE") - .media(Media.builder() - .description(Text.builder() - .text("My second post") - .build()) - .title(Text.builder() - .text("My Post 2") - .build()) - .status("READY") - .originalUrl("https://coderstower.com/2020/01/13/open-close-principle-by-example/") - .build()) + .description("My second post\n\n#tag1 #tag2") + .title("My second post") + .source("https://coderstower.com/2020/01/13/open-close-principle-by-example/") .build()) .build()) - .visibility(Visibility.builder() - .memberNetworkVisibility("PUBLIC") - .build()) + .visibility("PUBLIC") .build(); HttpEntity requestShare = new HttpEntity<>(linkedInShare, httpHeaders); @@ -241,6 +221,7 @@ public void publish_shareId_publicationSucced() throws MalformedURLException { HttpHeaders httpHeaders = new HttpHeaders(); httpHeaders.setContentType(MediaType.APPLICATION_JSON); httpHeaders.add("X-Restli-Protocol-Version", "2.0.0"); + httpHeaders.add("LinkedIn-Version", "202304"); httpHeaders.setBearerAuth("accessToken"); when(oauth2CredentialsRepository.getCredentials("linkedin")).thenReturn(Optional.of(OAuth2Credentials.builder() @@ -249,7 +230,7 @@ public void publish_shareId_publicationSucced() throws MalformedURLException { HttpEntity requestEntityProfile = new HttpEntity<>(httpHeaders); - when(restTemplate.exchange("https://api.linkedin.com/v2/me", HttpMethod.GET, requestEntityProfile, Profile.class)) + when(restTemplate.exchange("https://api.linkedin.com/v2/userinfo", HttpMethod.GET, requestEntityProfile, Profile.class)) .thenReturn(ResponseEntity.ok(Profile.builder() .sub("memberid") .build())); @@ -257,32 +238,22 @@ public void publish_shareId_publicationSucced() throws MalformedURLException { LinkedInShare linkedInShare = LinkedInShare.builder() .author("urn:li:person:memberid") .lifecycleState("PUBLISHED") + .commentary("My second post\n\n#tag1 #tag2") + .distribution(Distribution.builder().feedDistribution("MAIN_FEED").build()) + .lifecycleState("PUBLISHED") .content(Content.builder() .article(ArticleContent.builder() - .shareCommentary(Text.builder() - .text("My second post\n\n#tag1 #tag2") - .build()) - .shareMediaCategory("ARTICLE") - .media(Media.builder() - .description(Text.builder() - .text("My second post") - .build()) - .title(Text.builder() - .text("My Post 2") - .build()) - .status("READY") - .originalUrl("https://coderstower.com/2020/01/13/open-close-principle-by-example/") - .build()) + .description("My second post") + .title("My Post 2") + .source("https://coderstower.com/2020/01/13/open-close-principle-by-example/") .build()) .build()) - .visibility(Visibility.builder() - .memberNetworkVisibility("PUBLIC") - .build()) + .visibility("PUBLIC") .build(); HttpEntity requestShare = new HttpEntity<>(linkedInShare, httpHeaders); - when(restTemplate.exchange("https://api.linkedin.com/v2/ugcPosts", HttpMethod.POST, requestShare, Void.class)) + when(restTemplate.exchange("https://api.linkedin.com/rest/posts", HttpMethod.POST, requestShare, Void.class)) .thenReturn(ResponseEntity.ok().header("X-RestLi-Id", "shareId").build()); Publication publication = linkedInPublisher.publish(Post.builder()