Skip to content
This repository has been archived by the owner on Dec 11, 2018. It is now read-only.

initial pull request --work still on progress #44

Open
wants to merge 11 commits into
base: master
Choose a base branch
from
10 changes: 7 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ can be described with the following user stories and acceptance criteria:

* As a User, I want to view the list of published Tweets.
* The list must be sorted by publication date in descending order.

To pass this test, we expect software that also fulfills the following list of strategic user stories

* As a User, I want to add links to the tweet text without affecting the 140 character limit.
Expand All @@ -39,8 +39,8 @@ For the two new endpoints, you must accept this API:
* As a User, I want to discard tweets:
* POST /discarded
* Content-Type: application/json
* `{ "tweet": "%TWEET_ID%" }`
* `{ "tweet": "%TWEET_ID%" }`

* As a User, I want to view a list of discarded tweets:
* GET /discarded
* The response body format should be identical to the published tweets GET /tweet endpoint.
Expand Down Expand Up @@ -71,3 +71,7 @@ From the application folder, run
```sh
./gradlew test
```

## missing tasks
custom metrics -- instead of having it in the service, we could decouple it with two approaches: Filter or Aspect
test for metric
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@

@Configuration
public class InfrastructureConfiguration {
@Bean @ExportMetricWriter

@Bean
@ExportMetricWriter
public MetricWriter getMetricWriter(MBeanExporter exporter) {
return new JmxMetricWriter(exporter);
}
Expand Down
41 changes: 33 additions & 8 deletions src/main/java/com/scmspain/configuration/TweetConfiguration.java
Original file line number Diff line number Diff line change
@@ -1,22 +1,47 @@
package com.scmspain.configuration;

import com.scmspain.controller.TweetController;
import com.scmspain.controller.TweetCommandController;
import com.scmspain.controller.TweetExceptionHandlerController;
import com.scmspain.controller.TweetQueryController;
import com.scmspain.repositories.TweetRepository;
import com.scmspain.services.TweetService;
import org.springframework.boot.actuate.metrics.writer.MetricWriter;
import com.scmspain.services.converters.TweetConverterService;
import com.scmspain.services.validators.TweetMessageValidator;
import org.springframework.boot.actuate.metrics.CounterService;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.persistence.EntityManager;

@Configuration
//@ComponentScan //Scan controllers
public class TweetConfiguration {

@Bean
public TweetService getTweetService(TweetRepository tweetRepository, CounterService counterService, TweetMessageValidator tweetMessageValidator) {
return new TweetService(tweetRepository, counterService,tweetMessageValidator);
}

@Bean
public TweetCommandController tweetCommandController(TweetService tweetService) {
return new TweetCommandController(tweetService);
}

@Bean
public TweetQueryController tweetQueryController(TweetService tweetService, TweetConverterService converterService) {
return new TweetQueryController(tweetService,converterService);
}

@Bean
public TweetExceptionHandlerController tweetExceptionHandlerController(){
return new TweetExceptionHandlerController();
}

@Bean
public TweetService getTweetService(EntityManager entityManager, MetricWriter metricWriter) {
return new TweetService(entityManager, metricWriter);
public TweetConverterService converterService(){
return new TweetConverterService();
}

@Bean
public TweetController getTweetConfiguration(TweetService tweetService) {
return new TweetController(tweetService);
public TweetMessageValidator tweetMessageValidator(){
return new TweetMessageValidator();
}
}
59 changes: 59 additions & 0 deletions src/main/java/com/scmspain/controller/TweetCommandController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package com.scmspain.controller;

import com.scmspain.domain.dtos.DiscardTweetCommandDto;
import com.scmspain.domain.dtos.PublishTweetCommandDto;
import com.scmspain.domain.entities.Tweet;
import com.scmspain.services.TweetCommandService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;

import javax.validation.constraints.NotNull;

import static org.springframework.http.HttpStatus.CREATED;

@RestController
public class TweetCommandController {

final static private Logger logger = LoggerFactory.getLogger(TweetCommandController.class);

private TweetCommandService tweetCommandService;

public TweetCommandController(TweetCommandService tweetCommandService) {
this.tweetCommandService = tweetCommandService;
}

@PostMapping("/discarded")
@ResponseStatus(CREATED)
public void discardTweet(@RequestBody @NotNull DiscardTweetCommandDto discardTweetCommandDto) {
if (logger.isDebugEnabled()){
logger.debug("Discard Tweet "+discardTweetCommandDto);
}

this.tweetCommandService.discardTweet(discardTweetCommandDto.getTweet());
}

@PostMapping("/tweet")
@ResponseStatus(CREATED)
public void publishTweet(@RequestBody PublishTweetCommandDto publishTweetCommandDto) {
if (logger.isDebugEnabled()){
logger.debug("Publishing Tweet "+publishTweetCommandDto);
}

Tweet tweet = convertFromDto(publishTweetCommandDto);
this.tweetCommandService.publishTweet(tweet);
}

private Tweet convertFromDto(PublishTweetCommandDto command) {
Tweet tweet = new Tweet();
if (command!=null) {
tweet.setPublisher(command.getPublisher());
tweet.setTweet(command.getTweet());
}
return tweet;
}

}
41 changes: 0 additions & 41 deletions src/main/java/com/scmspain/controller/TweetController.java

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package com.scmspain.controller;

import com.scmspain.domain.exception.TweetIllegalArgumentException;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;

import static org.springframework.http.HttpStatus.BAD_REQUEST;

/**
* Class to handle the exceptions on the APIs specific for Tweet.
*/
@Order(Ordered.HIGHEST_PRECEDENCE)
@ControllerAdvice
public class TweetExceptionHandlerController extends ResponseEntityExceptionHandler {

@ExceptionHandler({TweetIllegalArgumentException.class,IllegalArgumentException.class})
@ResponseStatus(BAD_REQUEST)
@ResponseBody
public Object invalidArgumentException(Exception ex) {
if (logger.isDebugEnabled() ){
logger.debug("An exception has happened "+ ex);
}
String messageEx;
if (ex instanceof TweetIllegalArgumentException) {
messageEx = ((TweetIllegalArgumentException)ex).getMessageValidatorResult().toString();
} else {
messageEx = ex.getMessage();
}
return new Object() {
public String message = messageEx;
public String exceptionClass = ex.getClass().getSimpleName();
};
}
}

41 changes: 41 additions & 0 deletions src/main/java/com/scmspain/controller/TweetQueryController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package com.scmspain.controller;

import com.scmspain.domain.dtos.TweetQueryDto;
import com.scmspain.domain.entities.Tweet;
import com.scmspain.services.TweetQueryService;
import com.scmspain.services.converters.ConverterService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

import static java.lang.Boolean.FALSE;
import static java.lang.Boolean.TRUE;

@RestController
public class TweetQueryController extends TweetExceptionHandlerController {

private ConverterService<Tweet,TweetQueryDto> tweetConverterService;
private TweetQueryService tweetQueryService;

public TweetQueryController(TweetQueryService tweetQueryService, ConverterService<Tweet,TweetQueryDto> tweetConverterService) {
this.tweetQueryService = tweetQueryService;
this.tweetConverterService = tweetConverterService;
}

@GetMapping("/tweet")
public List<TweetQueryDto> listAllTweets() {
return getTweetQueryDtosByDiscardedFlag(FALSE);
}

@GetMapping("/discarded")
public List<TweetQueryDto> listAllDiscardedTweets() {
return getTweetQueryDtosByDiscardedFlag(TRUE);
}

private List<TweetQueryDto> getTweetQueryDtosByDiscardedFlag(Boolean aFalse) {
List<Tweet> tweets = this.tweetQueryService.listAllTweetsByDiscardedFlag(aFalse);
return tweetConverterService.toListItem(tweets);
}

}
21 changes: 21 additions & 0 deletions src/main/java/com/scmspain/domain/dtos/DiscardTweetCommandDto.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.scmspain.domain.dtos;

public class DiscardTweetCommandDto {

private Long tweet;

public Long getTweet() {
return tweet;
}

public void setTweet(Long tweet) {
this.tweet = tweet;
}

@Override
public String toString() {
return "DiscardTweetCommandDto{" +
"tweet=" + tweet +
'}';
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.scmspain.controller.command;
package com.scmspain.domain.dtos;

public class PublishTweetCommandDto {

public class PublishTweetCommand {
private String publisher;
private String tweet;

Expand All @@ -19,4 +20,12 @@ public String getTweet() {
public void setTweet(String tweet) {
this.tweet = tweet;
}

@Override
public String toString() {
return "PublishTweetCommandDto{" +
"publisher='" + publisher + '\'' +
", tweet='" + tweet + '\'' +
'}';
}
}
Original file line number Diff line number Diff line change
@@ -1,25 +1,15 @@
package com.scmspain.entities;
package com.scmspain.domain.dtos;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
/**
* Data Transfer Object for the entity {@link com.scmspain.domain.entities.Tweet}
*/
public class TweetQueryDto {

@Entity
public class Tweet {
@Id
@GeneratedValue
private Long id;
@Column(nullable = false)
private String publisher;
@Column(nullable = false, length = 140)
private String tweet;
@Column (nullable=true)
private Long pre2015MigrationStatus = 0L;

public Tweet() {
}

public Long getId() {
return id;
}
Expand Down Expand Up @@ -52,4 +42,13 @@ public void setPre2015MigrationStatus(Long pre2015MigrationStatus) {
this.pre2015MigrationStatus = pre2015MigrationStatus;
}

@Override
public String toString() {
return "TweetQueryDto{" +
"id=" + id +
", publisher='" + publisher + '\'' +
", tweet='" + tweet + '\'' +
", pre2015MigrationStatus=" + pre2015MigrationStatus +
'}';
}
}
Loading