Skip to content

Commit

Permalink
Provide engine ObjectMapper via custom interface (#615)
Browse files Browse the repository at this point in the history
* Bring back Primary ObjectMapper annotation

* Provide ObjectMapper to engine via custom interface to avoid multiple ObjectMapper beans

---------

Co-authored-by: Tuomo Ala-Vannesluoma <[email protected]>
  • Loading branch information
tuomoa and Tuomo Ala-Vannesluoma authored Aug 23, 2023
1 parent 8855204 commit 1b4c4ca
Show file tree
Hide file tree
Showing 16 changed files with 45 additions and 107 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import static java.lang.Runtime.getRuntime;

import java.util.concurrent.ThreadFactory;
import java.util.function.Supplier;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
Expand All @@ -26,6 +27,8 @@
@ComponentScan("io.nflow.engine")
public class EngineConfiguration {

public interface EngineObjectMapperSupplier extends Supplier<ObjectMapper> {}

/**
* Creates a workflow instance executor for processing workflow instances.
*
Expand Down Expand Up @@ -62,11 +65,11 @@ public ThreadFactory nflowThreadFactory() {
*/
@Bean
@NFlow
public ObjectMapper nflowObjectMapper() {
public EngineObjectMapperSupplier nflowObjectMapper() {
ObjectMapper mapper = new ObjectMapper();
mapper.setSerializationInclusion(NON_EMPTY);
mapper.registerModule(new JodaModule());
return mapper;
return () -> mapper;
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,12 @@
import org.springframework.transaction.interceptor.TransactionInterceptor;
import org.springframework.transaction.support.TransactionTemplate;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.inject.AbstractModule;
import com.google.inject.Provides;
import com.google.inject.Singleton;

import io.nflow.engine.config.EngineConfiguration;
import io.nflow.engine.config.EngineConfiguration.EngineObjectMapperSupplier;
import io.nflow.engine.config.NFlow;
import io.nflow.engine.config.db.DatabaseConfiguration;
import io.nflow.engine.config.db.Db2DatabaseConfiguration;
Expand Down Expand Up @@ -95,8 +95,8 @@ public WorkflowInstanceExecutor nflowExecutor(@NFlow ThreadFactory factory, Envi
@Provides
@NFlow
@Singleton
public ObjectMapper nflowObjectMapper() {
return engineConfiguration.nflowObjectMapper();
public EngineObjectMapperSupplier nflowObjectMapper() {
return () -> engineConfiguration.nflowObjectMapper().get();
}

@Provides
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import java.util.Map;
import java.util.Map.Entry;

import io.nflow.engine.config.EngineConfiguration.EngineObjectMapperSupplier;
import jakarta.inject.Inject;

import org.slf4j.Logger;
Expand Down Expand Up @@ -52,11 +53,11 @@ public class WorkflowDefinitionDao {
@Inject
public WorkflowDefinitionDao(SQLVariants sqlVariants,
@NFlow NamedParameterJdbcTemplate nflowNamedParameterJdbcTemplate,
@NFlow ObjectMapper nflowObjectMapper,
@NFlow EngineObjectMapperSupplier nflowObjectMapper,
ExecutorDao executorDao) {
this.sqlVariants = sqlVariants;
this.namedJdbc = nflowNamedParameterJdbcTemplate;
this.nflowObjectMapper = nflowObjectMapper;
this.nflowObjectMapper = nflowObjectMapper.get();
this.executorInfo = executorDao;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Type;

import io.nflow.engine.config.EngineConfiguration.EngineObjectMapperSupplier;
import jakarta.inject.Inject;

import org.springframework.stereotype.Component;
Expand All @@ -24,8 +25,8 @@ public class ObjectStringMapper {
private final ObjectMapper mapper;

@Inject
public ObjectStringMapper(@NFlow ObjectMapper nflowObjectMapper) {
this.mapper = nflowObjectMapper;
public ObjectStringMapper(@NFlow EngineObjectMapperSupplier nflowObjectMapper) {
this.mapper = nflowObjectMapper.get();
}

@SuppressWarnings("unchecked")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ public void nflowThreadFactoryInstantiated() {

@Test
public void nflowObjectMapperInstantiated() {
ObjectMapper mapper = configuration.nflowObjectMapper();
ObjectMapper mapper = configuration.nflowObjectMapper().get();
assertThat(mapper.canSerialize(DateTime.class), is(true));
assertThat(mapper.getSerializationConfig().getDefaultPropertyInclusion().getValueInclusion(),
is(JsonInclude.Include.NON_EMPTY));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import com.zaxxer.hikari.HikariDataSource;

import io.nflow.engine.config.EngineConfiguration;
import io.nflow.engine.config.EngineConfiguration.EngineObjectMapperSupplier;
import io.nflow.engine.config.NFlow;
import io.nflow.engine.config.db.H2DatabaseConfiguration;
import io.nflow.engine.internal.executor.WorkflowInstanceExecutor;
Expand Down Expand Up @@ -62,7 +63,7 @@ public void testEngineConfiguration() {
assertThat(((CustomizableThreadFactory) factory).getThreadNamePrefix(), is("nflow-executor-"));
assertThat(((CustomizableThreadFactory) factory).getThreadGroup().getName(), is("nflow"));

ObjectMapper mapper = injector.getInstance(Key.get(ObjectMapper.class, NFlow.class));
ObjectMapper mapper = injector.getInstance(Key.get(EngineObjectMapperSupplier.class, NFlow.class)).get();
assertThat(mapper.canSerialize(DateTime.class), is(true));
assertThat(mapper.getSerializationConfig().getDefaultPropertyInclusion().getValueInclusion(),
is(JsonInclude.Include.NON_EMPTY));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

import javax.sql.DataSource;

import io.nflow.engine.config.EngineConfiguration.EngineObjectMapperSupplier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.PropertySource;
Expand Down Expand Up @@ -53,7 +54,7 @@ public WorkflowInstanceDao workflowInstanceDao(SQLVariants sqlVariants,
@Bean
public WorkflowDefinitionDao workflowDefinitionDao(SQLVariants sqlVariants,
@NFlow NamedParameterJdbcTemplate nflowNamedParameterJdbcTemplate,
@NFlow ObjectMapper nflowObjectMapper,
@NFlow EngineObjectMapperSupplier nflowObjectMapper,
ExecutorDao executorDao) {
return new WorkflowDefinitionDao(sqlVariants,
nflowNamedParameterJdbcTemplate,
Expand Down Expand Up @@ -94,11 +95,11 @@ public PlatformTransactionManager transactionManager(DataSource ds) {

@Bean
@NFlow
public ObjectMapper objectMapper() {
public EngineObjectMapperSupplier objectMapper() {
ObjectMapper mapper = new ObjectMapper();
mapper.setSerializationInclusion(NON_EMPTY);
mapper.registerModule(new JodaModule());
return mapper;
return () -> mapper;
}

@Bean
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ public class WorkflowStateProcessorTest extends BaseNflowTest {
@Captor
ArgumentCaptor<List<WorkflowInstance>> workflows;

ObjectStringMapper objectMapper = new ObjectStringMapper(new ObjectMapper());
ObjectStringMapper objectMapper = new ObjectStringMapper(ObjectMapper::new);

WorkflowStateProcessor executor;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
@ExtendWith(MockitoExtension.class)
class ObjectStringMapperTest {

private final ObjectStringMapper mapper = new ObjectStringMapper(new ObjectMapper());
private final ObjectStringMapper mapper = new ObjectStringMapper(ObjectMapper::new);

@Mock
StateExecution execution;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,26 +1,18 @@
package nflow.kotlin

import com.fasterxml.jackson.databind.DeserializationFeature
import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.databind.SerializationFeature
import io.nflow.engine.config.EngineConfiguration
import io.nflow.engine.config.NFlow
import io.nflow.engine.service.WorkflowInstanceService
import io.nflow.engine.workflow.instance.WorkflowInstanceFactory
import io.nflow.rest.config.NflowRestApiPropertiesConfiguration
import io.nflow.rest.config.RestConfiguration
import io.nflow.rest.config.RestConfiguration.REST_OBJECT_MAPPER
import jakarta.inject.Inject
import jakarta.inject.Named
import nflow.kotlin.workflow.ExampleWorkflow
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.boot.context.event.ApplicationReadyEvent
import org.springframework.boot.runApplication
import org.springframework.context.annotation.*
import org.springframework.context.event.EventListener;
import org.springframework.context.annotation.Configuration
import org.springframework.context.annotation.Import
import org.springframework.context.event.EventListener

@Import(value = [EngineConfiguration::class, NflowRestApiPropertiesConfiguration::class])
@ComponentScan(value = ["io.nflow.rest"], excludeFilters = [ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = [RestConfiguration::class])])
@Import(RestConfiguration::class)
@Configuration
class WorkflowAppConfig

Expand All @@ -41,14 +33,6 @@ class WorkflowApplication {
.putStateVariable(ExampleWorkflow.VAR_COUNTER, 0)
.build())
}

@Primary
@Bean
@Named(REST_OBJECT_MAPPER)
fun nflowRestObjectMapper(@NFlow nflowObjectMapper: ObjectMapper): ObjectMapper = nflowObjectMapper.copy().apply {
configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false)
enable(DeserializationFeature.FAIL_ON_TRAILING_TOKENS)
}
}

fun main(args: Array<String>) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,33 +1,18 @@
package io.nflow.springboot.fullstack.gradle;

import com.fasterxml.jackson.databind.ObjectMapper;
import io.nflow.engine.config.EngineConfiguration;
import io.nflow.engine.config.NFlow;
import io.nflow.rest.config.NflowRestApiPropertiesConfiguration;
import io.nflow.engine.service.WorkflowInstanceService;
import io.nflow.engine.workflow.instance.WorkflowInstanceFactory;
import io.nflow.rest.config.RestConfiguration;
import jakarta.inject.Inject;

import jakarta.inject.Named;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.FilterType;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.Primary;
import org.springframework.context.event.EventListener;

import io.nflow.engine.service.WorkflowInstanceService;
import io.nflow.engine.workflow.instance.WorkflowInstanceFactory;

import static com.fasterxml.jackson.databind.DeserializationFeature.FAIL_ON_TRAILING_TOKENS;
import static com.fasterxml.jackson.databind.SerializationFeature.WRITE_DATES_AS_TIMESTAMPS;
import static io.nflow.rest.config.RestConfiguration.REST_OBJECT_MAPPER;

@SpringBootApplication
@Import({ EngineConfiguration.class, NflowRestApiPropertiesConfiguration.class })
@ComponentScan(value = "io.nflow.rest", excludeFilters = @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = RestConfiguration.class))
@Import(RestConfiguration.class)
public class DemoApplication {

@Inject
Expand All @@ -45,16 +30,6 @@ public void insertWorkflowInstance() {
.build());
}

@Primary
@Bean
@Named(REST_OBJECT_MAPPER)
public ObjectMapper nflowRestObjectMapper(@NFlow ObjectMapper nflowObjectMapper) {
ObjectMapper restObjectMapper = nflowObjectMapper.copy();
restObjectMapper.configure(WRITE_DATES_AS_TIMESTAMPS, false);
restObjectMapper.enable(FAIL_ON_TRAILING_TOKENS);
return restObjectMapper;
}

@Bean
public ExampleWorkflow exampleWorkflow() {
return new ExampleWorkflow();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,33 +1,18 @@
package io.nflow.springboot.fullstack.maven;

import com.fasterxml.jackson.databind.ObjectMapper;
import io.nflow.engine.config.EngineConfiguration;
import io.nflow.engine.config.NFlow;
import io.nflow.rest.config.NflowRestApiPropertiesConfiguration;
import io.nflow.engine.service.WorkflowInstanceService;
import io.nflow.engine.workflow.instance.WorkflowInstanceFactory;
import io.nflow.rest.config.RestConfiguration;
import jakarta.inject.Inject;

import jakarta.inject.Named;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.FilterType;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.Primary;
import org.springframework.context.event.EventListener;

import io.nflow.engine.service.WorkflowInstanceService;
import io.nflow.engine.workflow.instance.WorkflowInstanceFactory;

import static com.fasterxml.jackson.databind.DeserializationFeature.FAIL_ON_TRAILING_TOKENS;
import static com.fasterxml.jackson.databind.SerializationFeature.WRITE_DATES_AS_TIMESTAMPS;
import static io.nflow.rest.config.RestConfiguration.REST_OBJECT_MAPPER;

@SpringBootApplication
@Import({ EngineConfiguration.class, NflowRestApiPropertiesConfiguration.class })
@ComponentScan(value = "io.nflow.rest", excludeFilters = @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = RestConfiguration.class))
@Import(RestConfiguration.class)
public class DemoApplication {

@Inject
Expand All @@ -45,16 +30,6 @@ public void insertWorkflowInstance() {
.build());
}

@Primary
@Bean
@Named(REST_OBJECT_MAPPER)
public ObjectMapper nflowRestObjectMapper(@NFlow ObjectMapper nflowObjectMapper) {
ObjectMapper restObjectMapper = nflowObjectMapper.copy();
restObjectMapper.configure(WRITE_DATES_AS_TIMESTAMPS, false);
restObjectMapper.enable(FAIL_ON_TRAILING_TOKENS);
return restObjectMapper;
}

@Bean
public ExampleWorkflow exampleWorkflow() {
return new ExampleWorkflow();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,17 @@
package io.nflow.rest.config;

import static com.fasterxml.jackson.databind.DeserializationFeature.FAIL_ON_TRAILING_TOKENS;
import static com.fasterxml.jackson.databind.SerializationFeature.WRITE_DATES_AS_TIMESTAMPS;

import com.fasterxml.jackson.databind.ObjectMapper;
import io.nflow.engine.config.EngineConfiguration;
import io.nflow.engine.config.EngineConfiguration.EngineObjectMapperSupplier;
import io.nflow.engine.config.NFlow;
import jakarta.inject.Named;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.Primary;

import com.fasterxml.jackson.databind.ObjectMapper;

import io.nflow.engine.config.EngineConfiguration;
import io.nflow.engine.config.NFlow;
import static com.fasterxml.jackson.databind.DeserializationFeature.FAIL_ON_TRAILING_TOKENS;
import static com.fasterxml.jackson.databind.SerializationFeature.WRITE_DATES_AS_TIMESTAMPS;

@Configuration
@Import({ EngineConfiguration.class, NflowRestApiPropertiesConfiguration.class })
Expand All @@ -25,8 +22,8 @@ public class RestConfiguration {

@Bean
@Named(REST_OBJECT_MAPPER)
public ObjectMapper nflowRestObjectMapper(@NFlow ObjectMapper nflowObjectMapper) {
ObjectMapper restObjectMapper = nflowObjectMapper.copy();
public ObjectMapper nflowRestObjectMapper(@NFlow EngineObjectMapperSupplier nflowObjectMapper) {
ObjectMapper restObjectMapper = nflowObjectMapper.get().copy();
restObjectMapper.configure(WRITE_DATES_AS_TIMESTAMPS, false);
restObjectMapper.enable(FAIL_ON_TRAILING_TOKENS);
return restObjectMapper;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
public class CreateWorkflowConverterTest {

@Spy
private final ObjectStringMapper objectMapper = new ObjectStringMapper(new ObjectMapper());
private final ObjectStringMapper objectMapper = new ObjectStringMapper(ObjectMapper::new);

private CreateWorkflowConverter converter;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public void setup() {

@Test
public void nflowRestObjectMapperInstantiated() {
ObjectMapper restMapper = configuration.nflowRestObjectMapper(new ObjectMapper());
ObjectMapper restMapper = configuration.nflowRestObjectMapper(ObjectMapper::new);
assertThat(restMapper.getSerializationConfig().hasSerializationFeatures(WRITE_DATES_AS_TIMESTAMPS.getMask()), is(false));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ public void setup() {
resource = new WorkflowInstanceResource(workflowInstances, createWorkflowConverter, listWorkflowConverter,
workflowInstanceFactory, workflowInstanceDao);
lenient().when(workflowInstanceFactory.newWorkflowInstanceBuilder())
.thenReturn(new WorkflowInstance.Builder(new ObjectStringMapper(new ObjectMapper())));
.thenReturn(new WorkflowInstance.Builder(new ObjectStringMapper(ObjectMapper::new)));
}

@Test
Expand Down

0 comments on commit 1b4c4ca

Please sign in to comment.