Reputation: 111
In my spring boot application, I want to get an object/bean of a specific class based on the @RequestBody
value that is received. Is there a way to do the same
Interface
public interface Vehicle{
public String drive();
}
Implementation of The interface
@Component
public class Car implements Vehicle {
public String drive(){
return "Driving a car";
}
}
@Component
public class Bike implements Vehicle {
return "Riding a Bike";
}
Now in my controller based on the request body I want to get the bean of Either CAR
or Bike
.
Is there a way to do the same
Controller
@RestController
@RestMapping('type-of-vehicle')
public class VehicleSelectController{
@PostMapping
public String identify_Vehicle_Selected(@RequestBody vehicletype vehicletype_data){
/* ## Code to get the bean of vehicle type sent in the RequestBody */
// example vehicletype_data selected vehicle is car
// we get the bean of the 'CAR' class
// Returns the correct implementation of the type of vehicle selected by user
return vehicle.drive();
}
}
Are there any annotations that can be used to achieve the same more of I am trying to avoid making a config class that returns the correct object based on the vehicle type received
I was thinking something along this line
Wrong-way of Implementation
@RestController
@RestMapping('type-of-vehicle')
public class VehicleSelectController{
@PostMapping
public String identify_Vehicle_Selected(@RequestBody vehicletype vehicletype_data){
@Autowired
@Qualifiyer('${vehicletype_data}')
Vehicle vehicle_object
return vehicle_object.drive();
}
}
Is there a method to do something similar to the incorrect implementation
Upvotes: 1
Views: 3875
Reputation: 652
I found similar question: Get bean from ApplicationContext by qualifier
If it does not solve your problem, maybe try something like:
Vehicle
interface that check whether it is target vehicle by given data from request:boolean isTargetVehicle(final string valueFromRequest);
Example for car vehicle implementation:
public boolean isTargetVehicle(final string valueFromRequest) {
return "car".equals(valueFromRequest);
}
@Autowired
Collection<Vehicle> vehicles;
drive
method only on target vehicles. It returns value from drive
method, otherwise throws exception if vehicle support is not found:vehicles.stream().filter(v -> v.isTargetVehivle(dataFromRequest)).map(Vehicle::drive).findFirst().orElseThrow(() -> new Exception("vehicle not supported"));
In this approach you can easily add new vehicle without modifying existing code. And in addition it is better to use constructor injection.
Upvotes: 1
Reputation: 1903
You can use Factory Pattern. Create a bean factory for the getting the Vehicle bean.
@Component
public class VehicleFactory{
@Autowired
@Qualifier("bike") // bean name is same as class name with the first letter being lowercase
private Vehicle bike;
@Autowired
@Qualifier("car")
private Vehicle car;
public Vehicle getVehicle(VehicleType vehicleType){
if(vehicleType == VehicleType.CAR){ // Assuming VehicleType is an enum
return car;
} else if (vehicleType == VehicleType.BIKE){
return bike;
} else {
throw new IllegalArgumentException("No bean available for the type " + vehicleType);
}
}
}
Now in your controller,
@RestController
@RestMapping('type-of-vehicle')
public class VehicleSelectController{
@Autowired
VehicleFactory vehicleFactory;
@PostMapping
public String identify_Vehicle_Selected(@RequestBody vehicletype vehicletype_data){
return vehicleFactory.getVehicle(vehicletype_data).drive(); // handle the exception as needed
}
}
Upvotes: 3
Reputation: 159114
You can do it like this:
@Component
@Qualifier("Car")
public class Car implements Vehicle {
@Override
public String drive() {
return "Driving a car";
}
}
@Component
@Qualifier("Bike")
public class Bike implements Vehicle {
@Override
public String drive() {
return "Riding a Bike";
}
}
public class VehicleSelectController {
private Map<String, Vehicle> vehicles = new HashMap<>();
@Autowired
private void setVehicles(List<Vehicle> vehicles) {
for (Vehicle vehicle : vehicles) {
Qualifier qualifier = vehicle.getClass().getAnnotation(Qualifier.class);
if (qualifier != null)
this.vehicles.put(qualifier, vehicle);
}
}
@PostMapping
public String identify_Vehicle_Selected(@RequestBody vehicletype vehicletype_data) {
Vehicle vehicle = this.vehicles.get(vehicletype_data.getType());
if (vehicle == null)
throw new IllegalArgumentException("Unknown type: " + vehicletype_data.getType());
return vehicle.drive();
}
}
Upvotes: 0