Skip to content

Instantly share code, notes, and snippets.

@martinandersson
Last active December 1, 2016 15:36
Show Gist options
  • Save martinandersson/e6b7df7903e47acb7370ed6e2c5e46cc to your computer and use it in GitHub Desktop.
Save martinandersson/e6b7df7903e47acb7370ed6e2c5e46cc to your computer and use it in GitHub Desktop.
Configurator, passed to service by CDI.
class DefaultFacade implements Facade
{
@Inject
OrderService service;
@Override
public void buttonClicked() {
Instant dispatch = Instant.now().plus(2, ChronoUnit.HOURS);
Order order = service.createOrder(dispatch);
// ..
}
}
class DefaultService implements OrderService
{
@Inject
OrderFactory factory;
@Inject
Instance<OrderConfigurator> cfgInstance;
@Override
public Order createOrder(Instant dispatchDate) {
Order o = factory.createOrder(dispatchDate);
OrderConfigurator configurator = getInstanceOrNull(cfgInstance);
if (configurator != null) {
configurator.configure(order);
}
return o;
}
private static <T> T getInstanceOrNull(Instance<? extends T> instance) {
try {
return instance.get();
}
catch (UnsatisfiedResolutionException e) {
return null;
}
}
}
class MyOrderConfigurator implements OrderConfigurator
{
@Override
public void configure(Order order) {
// Do whatever to the order.
}
}
// This interface can not be generic. I.e, Configurator<T>.
// See https://github.com/MartinanderssonDotcom/java-ee-concepts/blob/master/src/test/java/com/martinandersson/javaee/cdi/resolution/GenericBeanUndeployableTest.java
interface OrderConfigurator {
void configure(Order order);
}
@martinandersson
Copy link
Author

martinandersson commented Dec 1, 2016

This is one way to let CDI pass the service an optional order configurator.

We could also let the facade and/or service accept an optional configurator from the client.

Also note that this example is kind of broken. We let the facade determine a default dispatch date (two hours from invocation time) that is sent to the service and then further passed down to the Order constructor. Hence, this example claims it is the responsibility of the facade to determine the dispatch date. But, we leave it to another optional entity (OrderConfigurator) to determine the rest.

We have to have a design for what is "reasonable defaults" and who set what. Furthermore, having the configurator outside the Order class render the Order class inherently mutable. Our configurator might have the responsibility to set "required" fields, but these fields now have the semantics of being "required" only at the time of our database persist.

It would be really cool if the service looked up the configurator, but passed this guy to the Order constructor. Hence, once the initialization routine (constructor) completes, the order is complete (this does violate a Java language principle that constructors shouldn't be overridable and/or call non-final methods). This would require the base line to have one default order configuration which must be specialized by projects.

If it is the case that having a configurator move all logic from the service to the configurator and the service ends up being a single-line method, then the service is the "configurator" and it make no sense to further pollute the type system. Instead, each project should specialize the service itself.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment