Reputation: 35
I have a factory class that creates an object. In my case, this is ObjectMapper (Jackson).
@Factory
public class JacksonFactory {
@Singleton
public ObjectMapper getObjectMapper() {
return new ObjectMapper().configure(FAIL_ON_UNKNOWN_PROPERTIES, false);
}
}
I want to inject it into a static field of the class:
public class JsonString {
@Inject
private static ObjectMapper mapper;
public static String of(Object object) {
try {
return mapper.writeValueAsString(object);
} catch (JsonProcessingException exception) {
throw new RuntimeException();
}
}
}
But, it doesn't work that way. I get a NullPointer every time I access the mapper static field. If I make the methods and the field non-static everything works well.
I didn’t find an explanation for this in the documentation, maybe I’m missing something or what is the problem with dependency injection?
Many thanks for the help! :)
UPDATE
Ok guys. I am not creating a static class, but creating an object and I want to inject it as a dependency into all objects that will be created. Why is the dependency not injected when I create inheritors of the JsonDto object?
@Singleton
public class JsonString {
@Inject
private ObjectMapper mapper;
public String of(Object object) {
try {
return mapper.writeValueAsString(this);
} catch (JsonProcessingException exception) {
throw new KyivAirException(exception);
}
}
}
I thought that every time when creating an object, Micronaut will find this bin in the context and substitute it. But that doesn't seem to be how it works. I am completely confused -_\
public abstract class JsonDto {
@Inject
private JsonString jsonString;
@Override
public String toString() {
return jsonString.of(this);
}
}
Upvotes: 1
Views: 2147
Reputation: 1261
i suggest try something like that:
First create your object converter which will take of converting the objects
@Singleton
public class ObjectConverter (private ObjectMapper mapper) {
public String of(Object object) {
try {
return mapper.writeValueAsString(this);
} catch (JsonProcessingException exception) {
throw new RuntimeException(exception);
}
}
}
Than have your dto like that (i prefer constructor injection over @inject)
public abstract class MyDto(private ObjectConverter converter) {
@Override
public String toString() {
return converter.of(this);
}
}
And finally your service, taking care of the dtos
@Singleton
public class MyDtoService(private ObjectConverter mapper) {
public String get(Long id) {
// TODO get the object from somewhere
return mapper.of(dto)
}
}
If we are talking about a dto that comes from the database i suggest something like that
interface MyJsonDbDto {
String decode(ObjectConverter mapper) {
return mapper.of(this)
}
}
public class MyDbDto implements MyJsonDbDto{
}
and the service therefore
public class MyDbDtoService(private ObjectConverter converter, private MyDbDtoRepository repository)
public String get(Long id) {
// TODO get the object from repository
return dto.decode(converter)
}
}
hope that helps and sorry i am mainly in kotlin, therefore my java is a little rusty ;-)
EDIT:
regarding your comment, i have an ugly idea, which could be considered as a some kind of intermediate solution for your refactoring process
create the service like that (use context, cause its not lazy loaded like a singleton)
@Context
public class MyDtoService {
public static ObjectConverter mapper;
public MyDtoService(ObjectConverter mapper) {
MyDtoService.mapper = mapper;
}
}
after that you can access it whithin your dto
public class MyDto {
@Override
public String toString() {
return MyDtoService.mapper.of(this);
}
}
Upvotes: 3