How to programmatically inject a Java CDI managed bean into a local variable in a (static) method
To inject an instance of class C
:
javax.enterprise.inject.spi.CDI.current().select(C.class).get()
This is available in CDI 1.1+
Get a CDI bean dynamically, NOT by injection
I found the answer here:
How to programmatically inject a Java CDI managed bean into a local variable in a (static) method
Need to use:
javax.enterprise.inject.spi.CDI.current().select(C.class).get()
Programmatic run-time injection/auto-wiring in quarkus
This is similar to this question.
How to programmatically inject a Java CDI managed bean into a local variable in a (static) method
javax.enterprise.inject.spi.CDI.current().getBeanManager().select(C.class).get()
To make sure that the bean class is manged use the io.quarkus.arc.Unremovable
annotation.
CDI for incoming JSON deserialised POJOs
Using a programmatical CDI approach you can achieve it with the following:
@Path("sample")
public class SampleResource {
@POST
@Consumes(MediaType.APPLICATION_JSON)
public Response message(MyPayload myPayload) {
return Response.ok(myPayload.getName()).build();
}
}
A sample business logic CDI bean
public class BusinessLogic {
public String doFoo(String name) {
return name.toUpperCase();
}
}
The payload:
public class MyPayload {
private String name;
private BusinessLogic businessLogic;
public MyPayload() {
this.businessLogic = CDI.current().select(BusinessLogic.class).get();
}
public String getName() {
return businessLogic.doFoo(this.name);
}
public void setName(String name) {
this.name = name;
}
}
and finally the beans.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/beans_2_0.xsd"
bean-discovery-mode="all">
</beans>
Hitting the endpoint returns the expected input as uppercase:
curl -v -d '{"name": "duke"}' -H 'Content-Type: application/json' http://localhost:9080/resources/sample
< HTTP/1.1 200 OK
< X-Powered-By: Servlet/4.0
< Content-Type: application/octet-stream
< Date: Thu, 02 Jul 2020 06:16:34 GMT
< Content-Language: en-US
< Content-Length: 4
<
* Connection #0 to host localhost left intact
DUKE
This way you inject the CDI bean in the default constructor which is called by JSON-B when it tries to serialize the incoming payload.
The other way was programatically loading the bean but I've read that
it's not good practice.
Not sure if there is any other solution to make this happen and let the CDI container take care of the injection.
Injection of stateless session bean into custom JsonDeserializer fails
Jon Peterson pointed me to the right direction. I finally chose to implement the 'hackish' solution, in a way. Please note that there are basically 2 options here (if you know another one, please let me know!). Short version:
- Hackish solution (the solution I chose): inject a bean programmatically using
javax.enterprise.inject.spi.CDI.current().select(UserFacadeRest.class).get()
as described in the accepted answer of the question mentioned by Jon or - Better (clean) solution (but also more elaborate): Redesign the logic to fill the missing fields after deserialization as suggested by Jon.
So for my question, the solution looks as follows:
1.
import javax.enterprise.inject.spi.CDI;
public class UserDeserializer extends JsonDeserializer<User> {
private final UserFacadeREST userFacade =
CDI.current().select(UserFacadeREST.class).get();
// Rest as before
}
2. In this case, in the deserialize
method of my JsonDeserializer
I would construct a User that just holds the userID. In every request method I would then have to examine all the users and replace them by the actual user by calling EntityManager.find(User.class, user.getUserID())
. This means more effort in the business logic as you have to keep in mind that everytime you need to work on a User
in a request method, you first have to do a query to get the 'full' User
object. In the first solution, this query is hidden from the business logic and already happens in the JsonDeserializer
.
public class UserDeserializer extends JsonDeserializer<User> {
@Override
public User deserialize(JsonParser parser, DeserializationContext context) throws IOException,
JsonProcessingException {
JsonNode node = parser.getCodec().readTree(parser);
int userId = (Integer) ((IntNode) node.get("userID")).numberValue();
return new User(userId); // Placeholder User object containing only the user ID, needs to be replaced in business logic
}
}
Related Topics
Checking If Unlimited Cryptography Is Available
What Are the Date Formats Available in Simpledateformat Class
Jaxb: How to Marshal Complex Nested Data Structures
Run Java File as Administrator with Full Privileges
Conversion from 12 Hours Time to 24 Hours Time in Java
Getting Xml Node Text Value with Java Dom
Maximum Size of a Method in Java 7 and 8
Java 8: How to Work with Exception Throwing Methods in Streams
Differencebetween String and Stringbuffer in Java
Create File with Given Size in Java
Why Would One Declare a Java Interface Method as Abstract