Skip to main content

spring_boot_starter_web 0.6.0 copy "spring_boot_starter_web: ^0.6.0" to clipboard
spring_boot_starter_web: ^0.6.0 copied to clipboard

Spring MVC for Dart: @RestController with @GetMapping and @PostMapping on dart:io, JSON bodies, @Valid, ProblemDetail errors, server-sent events, filters, CORS.

example/example.dart

// A REST API in a Spring Boot application: write the controller, the
// generator registers it and writes its request handlers (example.spring.dart,
// from `dart run build_runner build`). JSON goes through the ObjectMapper,
// `@Valid` checks request bodies, errors are answered as ProblemDetail.
//
//   dart run example/example.dart
//   curl localhost:8080/api/books/978-0
//   curl -N localhost:8080/api/books/added       # server-sent events
//   curl -i localhost:8080/api/books -H 'Content-Type: application/json' \
//       -d '{"isbn": "978-1", "title": "Emma"}'
import 'dart:async';

import 'package:spring_boot_starter_web/spring_boot_starter_web.dart';

import 'example.spring.dart';

class Book {
  const Book({required this.isbn, required this.title});
  final String isbn;
  final String title;
}

class NewBook {
  const NewBook({required this.isbn, required this.title});

  @NotBlank()
  @Size(min: 4, max: 13)
  final String isbn;

  @NotBlank()
  final String title;
}

class BookNotFound implements Exception {
  BookNotFound(this.isbn);
  final String isbn;
}

@Service()
class BookService {
  final _books = <String, Book>{};
  final _added = StreamController<Book>.broadcast();

  @PostConstruct()
  void init() {
    _books['978-0'] = const Book(isbn: '978-0', title: 'Dune');
  }

  Book find(String isbn) => _books[isbn] ?? (throw BookNotFound(isbn));

  Book add(NewBook book) {
    final added = _books[book.isbn] = Book(isbn: book.isbn, title: book.title);
    _added.add(added);
    return added;
  }

  Stream<Book> get added => _added.stream;
}

@RestController()
@RequestMapping('/api/books')
class BookController {
  BookController(this.books);
  final BookService books;

  @GetMapping('/{isbn}')
  Book find(@PathVariable() String isbn) => books.find(isbn);

  /// 201 with a `Location` header; an invalid body is a 400 ProblemDetail.
  @PostMapping()
  ResponseEntity<Book> create(@RequestBody() @Valid() NewBook book) {
    final added = books.add(book);
    return ResponseEntity.created(Uri.parse('/api/books/${added.isbn}'))
        .body(added);
  }

  /// Each added book as a server-sent event (`text/event-stream`).
  @GetMapping('/added')
  EventStream<Book> added() => EventStream(
    () => books.added.map((book) => ServerSentEvent(book, id: book.isbn)),
  );

  /// `application/problem+json`: `{"status": 404, "detail": ...}`.
  @ExceptionHandler()
  @ResponseStatus(HttpStatus.notFound)
  ProblemDetail notFound(BookNotFound e) => ProblemDetail.forStatusAndDetail(
    HttpStatus.notFound,
    'No book ${e.isbn}',
  );
}

@SpringBootApplication()
void main(List<String> args) => runApplication(args);
0
likes
160
points
239
downloads

Documentation

API reference

Publisher

verified publisherfarum-azula.org

Weekly Downloads

Spring MVC for Dart: @RestController with @GetMapping and @PostMapping on dart:io, JSON bodies, @Valid, ProblemDetail errors, server-sent events, filters, CORS.

Repository (GitHub)
View/report issues

Topics

#http #rest #server #spring

License

Apache-2.0 (license)

Dependencies

spring_boot_dart, spring_boot_starter_logging, spring_web_dart

More

Packages that depend on spring_boot_starter_web