Drew
Drew

Reputation: 463

Spring Autowired Repository in Abstract Class

I'm trying to create an abstract class that performs the common REST operations that are required, but can't work out if what I'm trying to do is possible. I've tried a number of approaches, but have stripped the code below right back to how it should work in my head

Classes updated as per suggestions below. Problem now is that the constructor in the concrete class isn't valid, as CustomerRepository isn't assignable to JpaRepository, though it extends that interface.

AbstractRestController

public abstract class AbstractRestController<T> {

  private final JpaRepository<T, Serializable> repository;

  public AbstractRestController(JpaRepository<T, Serializable> repository) {
    this.repository = repository;
  }

  @RequestMapping(value = "/{id}", method = RequestMethod.GET)
  public ResponseEntity<JsonResponseBody<T>> getOne(@PathVariable Long id) {
    T restObj = repository.findOne(id);
    JsonResponseBody<T> response = new JsonResponseBody<>(ResponseStatus.SUCCESS, restObj);
    return ResponseEntity.ok().contentType(MediaType.APPLICATION_JSON_UTF8).body(response);
  }

  protected JpaRepository<T, Serializable> getRepository() {
    return repository;
  }
}

CustomerController

@RestController
@RequestMapping(value = "/api/v1/customer")
public class CustomerController extends AbstractRestController<Customer> {

    @Autowired
    public CustomerController(CustomerRepository repository){
        super(repository);
    } 
}

CustomerRepository

public interface CustomerRepository extends JpaRepository<Customer, Long> {

}

Upvotes: 1

Views: 2114

Answers (1)

woemler
woemler

Reputation: 7169

Indeed, as @dino-tw mentions, you are trying to instantiate an abstract class with an undefined dependency. You can absolutely have an abstract controller class, and even define request handling methods that will be inherited by all subclasses. Try this instead:

public abstract class AbstractRestController<T, ID extends Serializable> {

    private final JpaRepository<T, ID> repository;  

    public AbstractRestController(JpaRepository<T, ID> repository){
        this.repository = repository;
    }

    @RequestMapping(value = "/{id}", method = RequestMethod.GET)
    public ResponseEntity<JsonResponseBody<T>> getOne(@PathVariable ID id) {
        T restObj = repository.findOne(id);
        JsonResponseBody<T> response = new JsonResponseBody<>(ResponseStatus.SUCCESS, restObj);      
        return ResponseEntity.ok().contentType(MediaType.APPLICATION_JSON_UTF8).body(response);
    }

    protected JpaRepository<T, ID> getRepository(){ return repository; }
}


@RestController
@RequestMapping(value = "/api/v1/customer")
public class CustomerController extends AbstractRestController<Customer, Long> {

    @Autowired
    public CustomerController(CustomerRepository repository){
        super(repository);
    }  

}

Upvotes: 6

Related Questions