У меня следующий код:
@Data
@Validated
@ConfigurationProperties
public class Keys {
private final Key key = new Key();
@Data
@Validated
@ConfigurationProperties(prefix = "key")
public class Key {
private final Client client = new Client();
private final IntentToken intentToken = new IntentToken();
private final Intent intent = new Intent();
private final OAuth oauth = new OAuth();
private final ResourceToken resourceToken = new ResourceToken();
@Valid @NotNull private String authorization;
@Valid @NotNull private String bearer;
...
}
}
Это экземпляр, представляющий файл свойств, например:
key.authorization=Authorization
key.bearer=Bearer
..
Поскольку у меня могут быть разные источники для свойств (файл свойств, MongoDB и т. д.) У меня есть клиент, который наследуется от ключей следующим образом:
Источник файлов свойств
@Component
@Configuration
@Primary
@PropertySource("classpath:${product}-keys.${env}.properties")
//@JsonAutoDetect(fieldVisibility = Visibility.ANY)
public class CustomerKeysProperties extends Keys {
}
Источник монго
@Data
@EqualsAndHashCode(callSuper=true)
@Component
//@Primary
@Document(collection = "customerKeys")
public class CustomerKeysMongo extends Keys {
@Id
private String id;
}
Я просто выбираю источник, который хочу использовать, аннотируя класс с помощью @Primary
.В приведенном выше примере CustomerKeysProperties
является активным источником.
Все это отлично работает.У меня возникает проблема, когда я пытаюсь преобразовать экземпляр CustomerKeysProperties
в JSON, как показано в следующем коде:
@SpringBootApplication
public class ConverterUtil {
public static void main(String[] args) throws Exception {
SpringApplication.run(ConverterUtil.class, args);
}
@Component
class CustomerInitializer implements CommandLineRunner {
@Autowired
private Keys k;
private final ObjectMapper mapper = new ObjectMapper();
@Override
public void run(String... args) throws Exception {
mapper.setVisibility(PropertyAccessor.FIELD, Visibility.ANY);
//mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
String jsonInString = mapper.writeValueAsString(k);
System.out.println(jsonInString);
}
}
}
Хотя k
содержит все установленные свойства, преобразование завершается неудачно:
Caused by: com.fasterxml.jackson.databind.exc.InvalidDefinitionException: No serializer found for class org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) (through reference chain: x.client.customer.properties.CustomerKeysProperties$$EnhancerBySpringCGLIB$$eda308bd["CGLIB$CALLBACK_0"]->org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor["advised"]->org.springframework.aop.framework.ProxyFactory["targetSource"]->org.springframework.aop.target.SingletonTargetSource["target"]->x.client.customer.properties.CustomerKeysProperties$$EnhancerBySpringCGLIB$$4fd6c568["CGLIB$CALLBACK_0"])
at com.fasterxml.jackson.databind.exc.InvalidDefinitionException.from(InvalidDefinitionException.java:77)
at com.fasterxml.jackson.databind.SerializerProvider.reportBadDefinition(SerializerProvider.java:1191)
И если я раскомментирую mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false)
, как предложено в журналах, у меня в Джексоне будет бесконечный цикл, вызывающий переполнение стека:
at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:155)
at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:727)
at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:719)
at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:155)
at com.fasterxml.jackson.databind.ser.impl.IndexedListSerializer.serializeContents(IndexedListSerializer.java:119)
at com.fasterxml.jackson.databind.ser.impl.IndexedListSerializer.serialize(IndexedListSerializer.java:79)
at com.fasterxml.jackson.databind.ser.impl.IndexedListSerializer.serialize(IndexedListSerializer.java:18)
at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:727)
at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:719)
at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:155)
..
Вопросы
В конце я просто хочу предоставить класс Util, который может конвертировать файл свойств в формате JSON, который будет храниться в MongoDB.
- Как я могу решить эту проблему?
- Не проходя через описанный выше объект, как я могу преобразовать файл свойств в JSON?
- Можно ли сохранить произвольный компонент Java в MongoDB с автоматическим преобразованием в JSON?
Было бы полезно ответить на любой из 3 приведенных выше вопросов.
Примечания
- Следует отметить, что я использую ломбок.Не уверен, что это проблема.
- Другое предположение, что я пытаюсь сериализовать управляемый bean-компонент Spring, и задействованный им прокси-сервер приводит к тому, что Джексон не может выполнять сериализацию?Если да, то что может быть поворотом?
Спасибо!