Skip to main content

18 - Enterprise Framework Preparation

Enterprise framework preparation. Before tackling frameworks like Spring, master the architectural patterns behind them: dependency injection, inversion of control, repository pattern, and configuration management.

What do you think about this article?

At a Glance

Enterprise framework preparation. Before tackling frameworks like Spring, master the architectural patterns behind them: dependency injection, inversion of control, repository pattern, and configuration management.

Preparation for Enterprise Frameworks

Before tackling frameworks like Spring, it's essential to understand the architectural patterns that underlie them: Dependency Injection and Inversion of Control.

What You'll Learn

  • Inversion of Control (IoC)
  • Dependency Injection (DI)
  • Repository and Service patterns
  • Preparation for Spring Framework

Inversion of Control (IoC)

With IoC, the control of creating and managing dependencies is "inverted" from application code to an external container.

Without IoC vs With IoC
// WITHOUT IoC: the application creates dependencies
class UserService {
    private UserRepository repository;

    public UserService() {
        // The class decides how to create the dependency
        this.repository = new MySqlUserRepository();
    }
}

// WITH IoC: dependencies are injected from outside
class UserService {
    private final UserRepository repository;

    // The dependency is provided by an external container
    public UserService(UserRepository repository) {
        this.repository = repository;
    }
}

Dependency Injection

Types of Injection
// 1. CONSTRUCTOR INJECTION (preferred)
class OrderService {
    private final OrderRepository repository;
    private final PaymentService paymentService;

    public OrderService(OrderRepository repository, PaymentService paymentService) {
        this.repository = repository;
        this.paymentService = paymentService;
    }
}

// 2. SETTER INJECTION
class OrderService {
    private OrderRepository repository;

    public void setRepository(OrderRepository repository) {
        this.repository = repository;
    }
}

// 3. FIELD INJECTION (not recommended without framework)
class OrderService {
    @Inject  // Requires DI framework
    private OrderRepository repository;
}

Simple DI Container

Mini DI Container
import java.util.*;
import java.util.function.Supplier;

// Simple DI container
class DIContainer {
    private Map<Class<?>, Supplier<?>> factories = new HashMap<>();
    private Map<Class<?>, Object> singletons = new HashMap<>();

    public <T> void register(Class<T> type, Supplier<T> factory) {
        factories.put(type, factory);
    }

    public <T> void registerSingleton(Class<T> type, T instance) {
        singletons.put(type, instance);
    }

    @SuppressWarnings("unchecked")
    public <T> T get(Class<T> type) {
        if (singletons.containsKey(type)) {
            return (T) singletons.get(type);
        }
        Supplier<?> factory = factories.get(type);
        if (factory == null) {
            throw new RuntimeException("No registration for: " + type);
        }
        return (T) factory.get();
    }
}

// Usage
public class Application {
    public static void main(String[] args) {
        DIContainer container = new DIContainer();

        // Register dependencies
        container.registerSingleton(UserRepository.class,
            new InMemoryUserRepository());
        container.register(UserService.class,
            () -> new UserService(container.get(UserRepository.class)));

        // Resolve
        UserService service = container.get(UserService.class);
    }
}

Repository Pattern

Repository Pattern
// Repository interface
interface Repository<T, ID> {
    Optional<T> findById(ID id);
    List<T> findAll();
    T save(T entity);
    void delete(T entity);
    boolean existsById(ID id);
}

// Specific implementation
interface UserRepository extends Repository<User, Long> {
    Optional<User> findByEmail(String email);
    List<User> findByRole(String role);
}

// Concrete implementation
class JpaUserRepository implements UserRepository {
    // Implementation with JPA/JDBC
}

class InMemoryUserRepository implements UserRepository {
    private Map<Long, User> storage = new HashMap<>();
    private long nextId = 1;

    @Override
    public Optional<User> findById(Long id) {
        return Optional.ofNullable(storage.get(id));
    }

    @Override
    public User save(User user) {
        if (user.getId() == null) {
            user.setId(nextId++);
        }
        storage.put(user.getId(), user);
        return user;
    }

    // ... other methods
}

Layered Architecture

Controller -> Service -> Repository
// LAYER 1: Controller (handles HTTP requests)
class UserController {
    private final UserService userService;

    public UserController(UserService userService) {
        this.userService = userService;
    }

    public Response createUser(CreateUserRequest request) {
        User user = userService.createUser(request);
        return Response.ok(user);
    }
}

// LAYER 2: Service (business logic)
class UserService {
    private final UserRepository repository;
    private final EmailService emailService;

    public UserService(UserRepository repository, EmailService emailService) {
        this.repository = repository;
        this.emailService = emailService;
    }

    public User createUser(CreateUserRequest request) {
        // Validation
        if (repository.findByEmail(request.getEmail()).isPresent()) {
            throw new UserAlreadyExistsException();
        }

        // Creation
        User user = new User(request.getName(), request.getEmail());
        User saved = repository.save(user);

        // Side effect
        emailService.sendWelcome(saved);

        return saved;
    }
}

// LAYER 3: Repository (data access)
// Already defined above

Next Steps: Spring Framework

What You'll Learn with Spring

  • Spring Core: IoC container, Beans, @Autowired
  • Spring Boot: auto-configuration, starters
  • Spring Data: JPA, MongoDB, Redis
  • Spring MVC: REST API, @Controller
  • Spring Security: authentication, authorization
Spring Boot Preview
// With Spring Boot, the code becomes much simpler
@RestController
@RequestMapping("/api/users")
public class UserController {

    @Autowired
    private UserService userService;

    @PostMapping
    public ResponseEntity<User> createUser(@RequestBody CreateUserRequest request) {
        User user = userService.createUser(request);
        return ResponseEntity.status(HttpStatus.CREATED).body(user);
    }

    @GetMapping("/{id}")
    public ResponseEntity<User> getUser(@PathVariable Long id) {
        return userService.findById(id)
            .map(ResponseEntity::ok)
            .orElse(ResponseEntity.notFound().build());
    }
}

@Service
public class UserService {
    @Autowired
    private UserRepository repository;

    // Business logic...
}

@Repository
public interface UserRepository extends JpaRepository<User, Long> {
    Optional<User> findByEmail(String email);
}

Congratulations!

You've completed the Java course! Now you have a solid foundation to tackle enterprise frameworks like Spring, Jakarta EE, or Quarkus.

Frequently asked questions

What is Inversion of Control (IoC) in the context of enterprise frameworks?

IoC is a design pattern where the control of creating and managing dependencies is "inverted" from application code to an external container.

What is Dependency Injection, and how does it relate to IoC?

Dependency Injection is a technique that uses an external container to manage dependencies, which is a key aspect of Inversion of Control (IoC).

What are some essential architectural patterns to understand before working with frameworks like Spring?

The article mentions Dependency Injection and Inversion of Control as essential architectural patterns to understand.

What Java course or foundation is required to tackle enterprise frameworks like Spring, Jakarta EE, or Quarkus?

A solid foundation in the Java course is necessary to tackle enterprise frameworks like Spring, Jakarta EE, or Quarkus.

Sources and further reading

Try These Tools

Free developer tools related to this topic.

Commenti

Caricamento commenti...

Sign in to comment

Discuss this article in the community

Join the Telegram group to discuss with other developers, ask questions and share your experiences.

Did you like this article?

Explore other content on the blog or discover my projects