Close

JAX-RS - Annotation Inheritance

[Last Updated: Oct 29, 2025]

JAX-RS annotations may be used on the methods and method parameters of a super-class or an implemented interface. Such annotations are inherited by a corresponding sub-class or implementation class method. Here following rules are applied:

  • Overriding methods should not have any JAX-RS annotations themselves, otherwise all annotations on super class/interface method are ignored.
  • Inheritance of class or interface annotations is not supported. That means only method level JAX-RS are inherited to the sub-classes.
  • Annotations on a super-class take precedence over those on an implemented interface.

Let's see an example, how to use this feature of JAX-RS.

Example

Creating a resource Interface

In this generic resource interface, we are going to provide various HTTP verb operations for a type T:

public interface AppResource<T> {

    @PUT
    @Path("{newId}")
    @Consumes(MediaType.APPLICATION_XML)
    String create(T t, @PathParam("newId") long newId);

    @DELETE
    @Path("{id}")
    String delete(@PathParam("id") long id);

    @POST
    @Consumes(MediaType.APPLICATION_XML)
    String update(T t);

    @GET
    @Produces(MediaType.APPLICATION_XML)
    List<T> list();

    @GET
    @Path("{id}")
    @Produces(MediaType.APPLICATION_XML)
    T byId(@PathParam("id") long id);
}

Implementing the interface

This implementation is going to have only one @Path annotation on the class.

@Path("employees")
public class EmployeeResource implements AppResource<Employee> {

    @Override
    public String create(Employee employee, long newId) {
        return EmployeeService.getInstance().create(employee, newId);
    }

    @Override
    public String delete(long id) {
        return EmployeeService.getInstance().delete(id);
    }

    @Override
    public String update(Employee employee) {
        return EmployeeService.getInstance().update(employee);
    }

    @Override
    public List<Employee> list() {
        return EmployeeService.getInstance().getEmployees();
    }

    @Override
    public Employee byId(long id) {
        return EmployeeService.getInstance().getEmployeeById(id);
    }
}

In above class, if we add any JAX-RS annotation on a method or a method parameters, then all annotations on the corresponding AppResource interface method will be ignored.

@XmlRootElement
public class Employee {
    private long id;
    private String name;
    private String dept;
    .............
}

To try examples, run embedded tomcat (configured in pom.xml of example project below):

mvn tomcat7:run-war

The client

Let's write JAX-RS client to test above resource:

public class EmployeeClient {
    private static Client client = ClientBuilder.newClient();
    private static WebTarget baseTarget = client.target("http://localhost:8080/employees");
    private static List<String> deptList = Arrays.asList("Admin", "IT", "Sale");

    public static void main(String[] args) {
        createEmployees();
        listEmployees();
        deleteEmployeeByIds(2, 4);
        Employee e = getEmployee(3);
        e.setDept("Marketing");
        updateEmployee(e);
        listEmployees();
    }

    private static Employee getEmployee(long id) {
        System.out.printf("-- getting employee by id: %s --%n", id);
        Employee e = baseTarget.path(Long.toString(id))
                               .request(MediaType.APPLICATION_XML)
                               .get(Employee.class);
        System.out.println("employee retrieved: " + e);
        return e;
    }

    private static void updateEmployee(Employee e) {
        System.out.println("-- updating employee --");
        System.out.println(e);
        String response = baseTarget.request(MediaType.APPLICATION_XML)
                                    .post(Entity.xml(e), String.class);
        System.out.println(response);
    }

    private static void deleteEmployeeByIds(long... ids) {
        System.out.printf("-- deleting employees: %s --%n",
                Arrays.toString(ids));
        for (long id : ids) {
            WebTarget target = baseTarget.path(Long.toString(id));
            Response r = target.request()
                               .delete();
            System.out.println(r.readEntity(String.class));
        }
    }

    private static void listEmployees() {
        System.out.println("-- getting employee list --");
        List<Employee> employees = baseTarget.request().get(
                new GenericType<List<Employee>>() {
                });
        employees.forEach(System.out::println);
    }

    private static void createEmployees() {
        System.out.println("-- making PUT requests --");
        for (int i = 1; i <= 5; i++) {
            Employee e = new Employee();
            e.setName("Employee" + i);
            int index = ThreadLocalRandom.current()
                                         .nextInt(0, 3);
            e.setDept(deptList.get(index));

            WebTarget target = baseTarget.path(Integer.toString(i));
            Response r = target.request()
                               .put(Entity.entity(e, MediaType.APPLICATION_XML));
            System.out.println(r.readEntity(String.class));
        }
    }
}

Output

-- making PUT requests --
Msg: employee created for id: 1
Msg: employee created for id: 2
Msg: employee created for id: 3
Msg: employee created for id: 4
Msg: employee created for id: 5
-- getting employee list --
Employee{id=1, name='Employee1', dept='Sale'}
Employee{id=2, name='Employee2', dept='Admin'}
Employee{id=3, name='Employee3', dept='Sale'}
Employee{id=4, name='Employee4', dept='Admin'}
Employee{id=5, name='Employee5', dept='Sale'}
-- deleting employees: [2, 4] --
Msg: employee deleted with id: 2
Msg: employee deleted with id: 4
-- getting employee by id: 3 --
employee retrieved: Employee{id=3, name='Employee3', dept='Sale'}
-- updating employee --
Employee{id=3, name='Employee3', dept='Marketing'}
employee updated : Employee{id=3, name='Employee3', dept='Marketing'}
-- getting employee list --
Employee{id=1, name='Employee1', dept='Sale'}
Employee{id=3, name='Employee3', dept='Marketing'}
Employee{id=5, name='Employee5', dept='Sale'}

Example Project

Dependencies and Technologies Used:

  • jersey-server 2.25.1: Jersey core server implementation.
  • jersey-container-servlet 2.25.1: Jersey core Servlet 3.x implementation.
  • JDK 1.8
  • Maven 3.3.9

Annotation Inheritance Example Select All Download
  • annotation-inheritance
    • src
      • main
        • java
          • com
            • logicbig
              • example
                • AppResource.java

    See Also