Simplify and automate web backend development
APACHE-2.0 License
Simply은 Spring 기반의 Restful API, Event-Driven 개발시 중복적인 코드를 줄여 준다. 중복적인 코드를 줄임으로써 Application 개발자가 Project의 목적인 Business Logic에 더 집중할 수 있게 하는 것이 목적이다.
기본적으로 Simply은 spring framework을 이용한 Restful API 등을 개발 할 때 도움이 되고자 한다. 추상화하는 내역으로는 @Service로 대표되는 Service, @RestConroller로 대표되는 Controllable 마지막으로 Event Driven을 위한 Entity변경 시 필요로한 Service에서의 Event Listener를 제공한다. 또한 부가적으로 Client모듈을 제공해 개발자가 마치 로컬 메소드를 호출하 듯 원격의 Restful API를 호출하여 사용할 수 있게 한다.
Maven 중앙 Repository로 부터 Library를 가져온다.
repositories {
mavenCentral()
}
[build.gradle]
implementation 'io.easywalk:simply-common:0.0.4.RELEASE'
implementation 'io.easywalk:simply-serviceable:0.0.4.RELEASE'
implementation 'io.easywalk:simply-controllable:0.0.4.RELEASE'
implementation 'io.easywalk:simply-eventable-kafka-binder:0.0.4.RELEASE'
implementation 'io.easywalk:simply-clientable:0.0.4.RELEASE'
simply:
eventable:
entity-base-package: io.easywalk.demo.entities
topic-property:
number-of-replicas: 1
number-of-partitions: 10
public interface SimplySpec<T, ID> {
T create(T createForm) throws Throwable;
T replaceById(ID id, T replace) throws Throwable;
T updateById(ID id, Map<String, Object> fields) throws Throwable;
T get(ID id) throws Throwable;
List<T> getAll() throws Throwable;
void deleteById(ID id) throws Throwable;
void delete(T entity) throws Throwable;
}
@Service
public class UserService extends AbstractServiceable<User, Long> {
protected UserService(UserRepository repository) {
super(repository);
}
}
@Service
public class UserService extends AbstractServiceable<User, Long> {
// Repository를 주입 받는다.
private final UserRepository repository;
protected UserService(UserRepository repository) {
super(repository);
this.repository = repository;
}
// 새로운 Method 를 작성한다.
public boolean isExist(Long id) {
return repository.existsById(id);
}
}
@EnableSimplyControllable
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
public interface Controllable<T1, T2> {
T1 create(T1 createForm) throws Throwable;
T1 replaceById(T2 id, T1 replace) throws Throwable;
T1 updateById(T2 id, Map<String, Object> fields) throws Throwable;
T1 get(T2 id) throws Throwable;
List<T1> getAll() throws Throwable;
void deleteById(T2 id) throws Throwable;
}
@RestController
@SimplyControllableResponse
@RequestMapping("/users")
public class UserController extends AbstractControllable<User, Long> {
public UserController(UserService service) {
super(service);
}
}
Method | ResponseCode | Reason | Comment |
---|---|---|---|
POST | 201 Created | 성공 | |
PUT | 200 OK | 성공 | |
PATCH | 200 OK | 성공 | |
DELETE | 204 No Contents | 성공 |
Method | ResponseCode | Reason | Comment |
---|---|---|---|
POST | 400 Bad Request | 실패 | 규격 오류 |
POST | 409 Conflict | 실패 | 이미 존재함 |
PUT | 404 Not Found | 실패 | 컨텐츠 미존재 |
PATCH | 404 No Contents | 실패 | 컨텐츠 미존재 |
PATCH | 400 Bad Request | 실패 | 규격 오류 |
undefined | 500 Internal Server Error | 실패 |
@EnableSimplyProducer
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
@Getter
@Setter
@ToString
@Entity
public class User implements SimplyEntity<Long> {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String name;
@NotNull
@Column(unique = true)
private String email;
}
@SimplyProducer("user")
@Service
public class UserService extends AbstractServiceable<User, Long> {
protected UserService(UserRepository repository) {
super(repository);
}
}
@Getter
@Setter
@ToString
@Entity
public class User implements SimplyEntity<Long> {
@Id
private Long id;
private String name;
@NotNull
@Column(unique = true)
private String email;
}
@Slf4j
@Component
public class UserListener extends AbstractSimplyConsumer<User, Long> {
private static String TOPIC = "user";
private final UserRepository repository;
protected UserListener(UserRepository repository) {
super(TOPIC, User.class);
this.repository = repository;
}
@SneakyThrows
@Override
public void on(SimplyEventableMessage<User> message) {
switch (message.getEventType()) {
case "CREATE":
case "UPDATE":
User user = convertToEntity(message.getPayload(), User.class);
repository.save(user);
break;
case "DELETE":
repository.deleteById(Long.valueOf(message.getKey()));
break;
default:
log.error("messsage {}", message);
}
}
}