Skip to content

And1sS/Tiny-boot

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

21 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Tiny Boot

What is it?

Tiny boot is small PoC of web mvc and database frameworks for building web applications.
Based on Java JDBC API and Servlet API. For Servlet containers embeded version of Tomcat is used.

What about features?

Tiny boot contains Spring like MVC framework and simple ORM(a bit like Spring Data JDBC).

MVC

This MVC framework implementation contains:

To define simple REST handler you need to create class, annotate it with @RestController and create some public handler methods.
For example:

@RestController
@RequestMapping("/api/user")
public class UserResource {

    private final ObjectMapper objectMapper = new ObjectMapper();
    private final UserService userService;

    public UserResource(UserService userService) {
        this.userService = Objects.requireNonNull(userService);
    }

    @GetMapping("/all")
    public ResponseEntity getAllUsers() throws JsonProcessingException {
        return ResponseEntity.ok(objectMapper.writeValueAsString(userService.findAllUsers()));
    }

    @PostMapping
    public ResponseEntity createUser(@RequestBody String body) throws JsonProcessingException {
        final User user = objectMapper.readValue(body, User.class);
        return ResponseEntity.ok(objectMapper.writeValueAsString(userService.save(user)));
    }
}

Then you need to register this handler into HandlerMapper and pass it into DispatcherServlet instance. Like this:

final HandlerMapper handlerMapper = new HandlerMapperImpl(new HandlerRegistryImpl());
handlerMapper.registerHandler(new UserResource(userService));

final Tomcat tomcat = getTomcat(8080, handlerMapper);

Just like in Spring MVC, but with reduced functionality. Full example can be found at: UserResource.java.

ORM

My implementation of simple orm contains:

  • Fixed size JDBC connections pool. Implementation here
  • Jdbc Types converters and their registry. Implementation here
  • Entity mapping with @Entity, @Table, @Column just like in JPA. (no relationships mapping implemented for now).
  • Spring-like Repository interfaces with @Query methods and arguments, Entity mapping. Implementation here
  • Spring-like thread bound @Transactional capabilities with transaction propagation and inner transactions managed by Transaction Manager. Implementation here.

To define simple repository and connect it to the database you need to:

  1. create interface with @Query methods and annotate it with @Repository. For example:
public interface UserRepository {

    @Query("SELECT id, login, first_name, last_name, password FROM usr WHERE id = :id")
    Optional<User> findUserById(Long id);

    @Query("INSERT INTO usr (id, login, first_name, last_name, password) VALUES" +
            " (:id, ':login', ':firstName', ':lastName', ':password')")
    void save(Long id, String login, String firstName, String lastName, String password);

    @Query("SELECT * FROM usr WHERE first_name = ':firstName'")
    List<User> findUsersWithName(String firstName);

    @Query("SELECT * FROM usr")
    List<User> findAllUsers();

    @Query("select nextval('public.usr_sequence')")
    Long getNextId();

    @Query("DELETE FROM usr WHERE id = :id")
    void deleteUserWithId(Long id);
}
  1. Create connection pool like so:
final Properties applicationProperties = PropertiesUtil.loadProperties("application.properties");
final JdbcConnectionOptions jdbcConnectionOptions = getJdbcConnectionOptions(applicationProperties);

final JdbcConnectionFactory jdbcConnectionFactory =
        new JdbcFixedConnectionPoolFactoryImpl(10, jdbcConnectionOptions);
final JdbcStatementFactory jdbcStatementFactory = new JdbcStatementFactoryImpl(jdbcConnectionFactory);

private static JdbcConnectionOptions getJdbcConnectionOptions(Properties applicationProperties) {
    return JdbcConnectionOptions.builder()
            .url(String.format("jdbc:postgresql://%s", applicationProperties.getProperty("database.url")))
            .user(applicationProperties.getProperty("database.user"))
            .password(applicationProperties.getProperty("database.password"))
            .build();
}
  1. Create JdbcTypeConverterRegistry like so:
return new JdbcTypeConverterRegistryImpl()
                .registerTypeConverter(new JdbcStringTypeConverter())
                .registerTypeConverter(new JdbcLongTypeConverter());
  1. Create ResultSetMapper like so:
final ResultSetMapper resultSetMapper = new ResultSetMapper(jdbcTypeConverterRegistry);
  1. Create proxy to combine all together:
final UserRepository userRepository = (UserRepository) Proxy.newProxyInstance(
                UserRepository.class.getClassLoader(),
                new Class[]{UserRepository.class},
                new RepositoryInvocationHandler(
                        jdbcStatementFactory, resultSetMapper, (a, b, c) -> null, jdbcTypeConverterRegistry));

Additionally, to add transaction management:

  1. Annotate your service class or its method with @Transactional just like in Spring:
@Transactional
public class UserServiceImpl implements UserService {

    final UserRepository userRepository;

    public UserServiceImpl(UserRepository userRepository) {
        this.userRepository = Objects.requireNonNull(userRepository);
    }

    @Override
    @Transactional(propagationLevel = Transactional.PropagationLevel.REQUIRES_NEW)
    public Optional<User> findUserById(Long id) {
        return userRepository.findUserById(id);
    }

    ...other methods
}
  1. Get proxied with transactions instance of your service:
TransactionalUtil.wrapInTransaction(
                new UserServiceImpl(userRepository),
                UserService.class,
                jdbcConnectionFactory,
                transactionManager)

Full example can be found in this repository under domain, repository, resource and service packages + Application.java.

About

Small PoC of ORM and web MVC frameworks(Spring like) built up on Java Reflection, JDBC and Servlet APIs

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages