Issue
I want to deserialize a generic enum. Sender and receiver use ObjectMapper
for MAPPER
:
String data = MAPPER.writeValueAsString(new ChangeState(this.state.toString(), this.state.getClass()));
bus.talkAsync(exchangeName, ROUTE_SET_STATE, data);
The Class ChangeState
public record ChangeState<E extends Enum<E>>(String someInfo, String state, Class<E> stateType) {}
The object being sent could look like this:
{"someInfo":"Test","state":"IDLE","stateType":"com.demo.common.states.ServiceAState"}
{"someInfo":"Test","state":"SOME","stateType":"com.demo.common.states.ServiceBState"}
I deserialize the message like this:
ChangeState<? extends Enum<?>> changeState = MAPPER.readValue(message, ChangeState.class);
But I'm unable to use the enum afterwards. How can I get back the enum (e.g. with valueOf
)?
What I've tried
Cast
The following does not work, because stateType
is an unknown class:
Class<? extends Enum<?>> stateType = changeState.stateType();
Enum<?> state = (stateType) changeState.state(); // Error thrown here for the cast type
Transmit the enum as enum
I tried to send the enum directly:
public record ChangeState<E extends Enum<E>>(String someInfo, E state) {}
But this leads to an error, because the enum type can't be identified, since the message looks like this: {"someInfo":"Test","state":"IDLE"}
.
Additional
- Each service has it's own state enum, since each service can have different states. The main target ist to make a service, which keeps track of all the states of every other service
- It's a multi module project. Every module uses the
com.demo.common
module to share classes. The used enums are usable in all modules. bus
is a RabbitMQ BusConnector.
Solution
When you have a constant name and a class, you can use the static two-argument valueOf method to convert the name to an enum value:
String name = changeState.state();
Class<? extends Enum<?>> type = changeState.stateType();
Enum<?> state = Enum.valueOf(type, name);
Answered By - VGR
Answer Checked By - Pedro (JavaFixing Volunteer)