or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

codecs.mdhttp-clients.mdhystrix.mdindex.mdjaxrs.mdjson-processing.mdxml-processing.md
tile.json

jaxrs.mddocs/

JAX-RS Support

Feign JAX-RS module enables Feign HTTP clients to use standard JAX-RS 1.1 specification annotations instead of Feign's proprietary annotations. It provides annotation processing capabilities that translate JAX-RS annotations into Feign's internal request templates.

Capabilities

JAX-RS Contract

The main contract class that processes JAX-RS annotations and converts them to Feign request templates.

/**
 * Contract implementation that processes JAX-RS annotations.
 * Extends Contract.BaseContract to provide JAX-RS 1.1 annotation support.
 */
public final class JAXRSContract extends Contract.BaseContract {
    
    /** Accept header constant */
    static final String ACCEPT = "Accept";
    
    /** Content-Type header constant */
    static final String CONTENT_TYPE = "Content-Type";
    
    /**
     * Parses and validates method metadata from JAX-RS annotated methods.
     * @param targetType The interface class containing the method
     * @param method The method to parse
     * @return MethodMetadata containing parsed request information
     */
    protected MethodMetadata parseAndValidateMetadata(Class<?> targetType, Method method);
}

Supported JAX-RS Annotations

Type-Level Annotations

Type-level annotations apply to the entire interface class.

/**
 * @Path - Defines base path for all methods in the interface
 * Applied to interface classes to set common URL prefix
 */
@Path("/api/v1")
interface MyAPI {
    // methods inherit the base path
}

/**
 * @Produces - Sets default Accept header for all methods
 * First media type value is used as Accept header
 */
@Produces("application/json")
interface MyAPI {
    // methods inherit the Accept header
}

/**
 * @Consumes - Sets default Content-Type header for all methods  
 * First media type value is used as Content-Type header
 */
@Consumes("application/json")
interface MyAPI {
    // methods inherit the Content-Type header
}

Method-Level Annotations

Method-level annotations define HTTP method and additional request properties.

/**
 * HTTP Method Annotations - Set the HTTP method for the request
 * Supported: @GET, @POST, @PUT, @DELETE, @HEAD, @OPTIONS, @PATCH
 */
@GET
@POST  
@PUT
@DELETE
// Any annotation with @HttpMethod meta-annotation

/**
 * @Path - Appends path to the base URL, supports path parameters
 * Can include path parameters with optional regex patterns
 */
@Path("/users/{id}")
@Path("/search/{query:.+}")  // with regex
@Path("/items/{id:[0-9]+}")  // numeric regex

/**
 * @Produces - Sets Accept header for this method (overrides type-level)
 * First media type value is used
 */
@Produces("application/xml")

/**
 * @Consumes - Sets Content-Type header for this method (overrides type-level)
 * First media type value is used  
 */
@Consumes("application/xml")

Parameter-Level Annotations

Parameter-level annotations bind method parameters to different parts of the HTTP request.

/**
 * @PathParam - Links parameter value to path template variable
 * Parameter name must match template variable name
 */
@PathParam("id") String userId

/**
 * @QueryParam - Links parameter to query parameter
 * Null values are skipped (query parameter not included)
 */
@QueryParam("filter") String filter
@QueryParam("limit") Integer limit  // null skips parameter

/**
 * @HeaderParam - Links parameter to HTTP header
 * Parameter value becomes header value
 */
@HeaderParam("Authorization") String authToken
@HeaderParam("User-Agent") String userAgent

/**
 * @FormParam - Links parameter to form data field
 * Used with application/x-www-form-urlencoded content type
 */
@FormParam("username") String username
@FormParam("password") String password

Usage Examples

Basic JAX-RS Client

import feign.Feign;
import feign.jaxrs.JAXRSContract;
import javax.ws.rs.*;
import java.util.List;

@Path("/api/v1")
@Produces("application/json")
interface UserAPI {
    @GET
    @Path("/users/{id}")
    User getUser(@PathParam("id") String userId);
    
    @GET
    @Path("/users")
    List<User> searchUsers(@QueryParam("name") String nameFilter,
                          @QueryParam("active") Boolean activeOnly);
    
    @POST
    @Path("/users")
    @Consumes("application/json")
    User createUser(User user);
}

// Create client with JAX-RS contract
UserAPI userAPI = Feign.builder()
    .contract(new JAXRSContract())
    .target(UserAPI.class, "https://api.example.com");

Path Parameters with Regex

interface ItemAPI {
    @GET  
    @Path("/items/{id:[0-9]+}")
    Item getItem(@PathParam("id") String id);
    
    @GET
    @Path("/search/{query:.+}")
    List<Item> search(@PathParam("query") String searchQuery);
}

Form Parameters

interface AuthAPI {
    @POST
    @Path("/login")
    @Consumes("application/x-www-form-urlencoded")
    Token login(@FormParam("username") String username,
                @FormParam("password") String password,
                @FormParam("remember") Boolean remember);
}

Headers and Content Negotiation

@Produces("application/json")  // Default Accept header
interface APIClient {
    
    @GET
    @Path("/data")
    @Produces("application/xml")  // Override Accept header for this method
    Data getDataAsXML();
    
    @POST
    @Path("/data")  
    @Consumes("application/json")  // Content-Type for request body
    void createData(Data data, @HeaderParam("X-Custom") String customHeader);
}

Installation

Add the JAX-RS module dependency:

dependencies {
    compile 'com.netflix.feign:feign-jaxrs:8.18.0'
    compile 'javax.ws.rs:jsr311-api:1.1.1'
}

Limitations

  • Client-focused: JAX-RS annotations were designed for servers, not clients
  • Best-effort compatibility: Does not implement 100% of JAX-RS specification
  • JAX-RS 1.1 only: Targets JAX-RS 1.1 specification, not newer versions
  • Interface-only: Only processes Java interfaces, not abstract or concrete classes
  • Single media type: Only uses first value from @Produces/@Consumes arrays

Error Handling

The JAX-RS contract validates annotation values and throws IllegalStateException for invalid configurations:

  • Empty or null @Path values
  • Empty or null parameter annotation values (@PathParam, @QueryParam, etc.)
  • Empty @Produces or @Consumes arrays
  • Multiple HTTP method annotations on the same method