How to @autowire some bean into JsonSerializer?
Asked Answered
T

4

32

I am using lazy loading with hibernate in my web app.

I would like to load some objects from the database at the parsing stage of the server response

@Component
public class DesignSerializer extends JsonSerializer<Design> {
@Autowired
IDesignService designService; <-- is null

}

Which is totally understandable because DesignSerializer is being instantiated with the "new" operator for each object.

I am sure there is a way to inject my bean into that serializer when ever it is created, I just don't know how.

Can you guys help me or point me in the right direction.

Talton answered 10/7, 2013 at 16:31 Comment(6)
If DesignSerializer is mark with @Component, it's suppose to be a bean if I'm not mistaken. You could grab the bean that was created by spring?Camilla
how?, this serializer is being called by spring after finishing the controller with @ResponseBodyTalton
don't you have an Application Context that you use getBean on it?Camilla
No. its spring MVC. and everything is annotatedTalton
Sorry it is me that misread your comment.Camilla
If Spring isn't managing this bean, then it can't inject anything into it.Doone
F
34

Solution is SpringBeanAutowiringSupport if you are using Spring Framework 2.5+.

public class DesignSerializer extends JsonSerializer<Design> {

    @Autowired
        IDesignService designService;
    }

    public DesignSerializer(){
        SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this);    
    }

...

}

I Hope that help you

Fornof answered 4/2, 2014 at 20:41 Comment(7)
Awesome. So simple compared to other suggestions all over the Web.Jaques
+1 for SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this); It solve my problem too.Strobel
can you please tell me how to use the autowire in my case with jackson? #35436779Malpighi
Does it work if you use a specific bean with @Qualifier?Brew
@JosselinePerdomo Yes, it doesFornof
It doesn't seem to be working in junit tests?Debacle
It does when the test runs with SpringRunnerFornof
H
23

We had the same problem with JsonSerializer and Spring autowiring. The solution that worked for us was to make two constructors. One for Spring which sets the dependency as a static field, and another one that is used by the Jackson initialisation.

This works because the Spring dependency injection (autowiring) happens before Jackson initialises the serializer.

@Component
public class MyCustomSerializer extends JsonSerializer<String> {

    private static IDesignService designService;

    // Required by Jackson annotation to instantiate the serializer
    public MyCustomSerializer() { }

    @Autowired
    public MyCustomSerializer(IDesignService designService) {
        this.designService = designService;
    }

    @Override
    public void serialize(String m, JsonGenerator gen, SerializerProvider s) {
        gen.writeObject(MyCustomSerializer.designService.method(..));
    }
}
Hadlock answered 3/7, 2014 at 11:5 Comment(1)
Somehow I dont like the solution but I don't know how to do it on a better way. So I follow this way :-)Canica
T
4

I Solved the problem by creating a static field in a different bean and then @Autowire its setter method.

@Service("ToolBox")
@Transactional
public class ToolBox 
{
    static Logger logger = Logger.getLogger(ToolBox.class);
        
    private static IService service;
    
    @Autowired
    public void setService(IService service)
    {
        ToolBox.service = service;
    }
    
    public static IService getService()
    {
        return ToolBox.service;
    }
}

like shown in this thread: Can you use @Autowired with static fields?

Talton answered 10/7, 2013 at 19:42 Comment(0)
N
2

If you're using Spring Boot, @JsonComponent will do the autowiring for you.

@JsonComponent
public class DesignSerializer extends JsonSerializer<Design> {
    @Autowired
    private DesignService designService;
}

Testing this serializer can then be done while autoconfiguring json support.

@AutoConfigureJson
@SpringBootTest
class DesignSerializerTest {

    @Autowired
    private ObjectMapper objectMapper;
    
    @Test
    void testDesignSerializer() {
        objectMapper.writer().writeValueAsString(new Design());
    }
}    
Noodlehead answered 27/4, 2023 at 6:30 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.