View on GitHub RESTX     the lightweight Java REST framework

RESTX 0.35

   

Today we are very happy to announce release 0.35 of RESTX, the lightweight, modular, feature rich, blazing fast and open source Java REST framework.

New and Noteworthy

Better cold classes management (PR #175)

Several new things have been added about cold classes :

  • It permits to add inherited classes of cold components (components being loaded in the main factory, such as AutoStartable ones) in cold classes list.
  • It adds a way to declare cold classes using a property: restx.cold.classes. The property value is a list of fqcn separated by ,.
  • It adds a way to declare cold classes using a resource file: META-INF/cold-classes.list. Resources will be loaded from the classloader, and every classes listed will be added to the cold classes list. The file must contains a list of fqcn, one per line.
  • It provides a way to fulfil the resource file using a new annotation: @Cold. So every classes annotated with @Cold will be added to the resource file.

[breaking] Security roles are now interpolated (PR #223)

Security roles used in @RolesAllowed annotation can now be interpolated with query parameters and path parameters.

For example :

@GET("/security/{companyId}/{subCompanyId}")
@RolesAllowed("EDIT_COMPANY_{companyId}_{subCompanyId}")
public String editSubCompany(String companyId, String subCompanyId){
    // ....
}

Also, you can add wildcarded roles to your principal, such as EDIT_COMPANY_1234_* : the special * in role name will match any role parameter value meaning users having role EDIT_COMPANY_1234_* will be able to call any /security/1234/* url without hitting any 403 FORBIDDEN response.

This feature may be particularly of interest if you are able to generate the whole security roles attached to a user when he authenticates. An example usage of such role definition & usage may be found in the samplest’s CompanyAndSubCompanyRoles enum, SecuredResource and principals declarations.

Unified and improved Query, Path and Body params handling (PR #177)

Query & Path parameters are now both handled through MainStringConverter, itself based on Jackson registered deserializers.

It means you can now use the same deserializer for every types of parameters (initially, for instance, you were not able to use DateTime in PATH parameters .. now you can).

Also, Aggregated types are now handled in such parameters, like List<BaseType>, Iterable<BaseType> or BaseType[] (as soon as SimpleType is what we call a BaseType, that is to say a type which would represent a “single” value : an Integer, a String, a Date etc. which could be handled by MainStringConverter component)

Parameterized types handling (based on generics) in every types of parameters (path, query, body) have been greatly improved as well, supporting any level of generics. For instance something like
Map<Boolean, Map<Tuple<String,Tuple<Integer,Float>,String>,String>> would not generate a compilation error during annotation processing.

Optional support has been improved on parameters :

  • allowing to take generics parameterized types (like Optional<List<Long>>)
  • Body content and Path parameters can now be Optional
  • as before, non-Optional parameters are implicitely mandatory, no matter its parameter type

For the internals, parameters deserialization are now handled by dedicated @Components which implement the EndpointParameterMapper interface. A factory component (EndpointParameterMapperFactory with DefaultEndpointParameterMapperFactory default implementation) is responsible to guess the appropriate EndpointParameterMapper which will be used for deserialization depending on target type to deserialize. This guessing is made only once during Route construction (so that there is no performance impact during request processing).

Currently, 3 EndpointParameterMapper are provided by DefaultEndpointParameterMapperFactory :

Also, if you want to recover old RestX 0.34 behaviour, we provided a LegacyEndpointParameterMapperFactory and a LegacyEndpointParameterMapper which are not taken into account by default (due to their priority compared to above component). If you want to re-enable it, simply change their priority and you will get back 0.34 parameters deserialization handling.

Because of those important changes, if you implemented your own StdEntityRoutes, you will likely have to change a lot of stuff :

  • you will have to pass a EndpointParameterMapperRegistry and declare an array of ParamDefs in StdEntityRoute’s constructor those ParamDef attributes represent parameter metadata used by EndpointParameterMapperFactory to guess EndpointParameterMapper.
  • you will have to resolve input endpoint parameter differently: have a look at a generated ResourceRouter class taking the same parameters in order to know how to handle those input endpoint parameters.

Request Header params and annotation aliases (PR #277)

A new @Param annotation kind has been introduced : Kind.HEADER allowing to inject request headers into your @RestxResource’s endpoints.

As other @Param annotations, you can either use @Param’s value field for header name (@Param(value="X-My-Header", kind=Kind.HEADER)) or implicitely use parameter variable name, even if it is unlikely to work properly : header names start with an uppercase which is not fitting Java variable naming best practices, and dashes are used as word separator whereas dashes are forbidden in Java variable names.

New annotation have been introduced aliasing different types of common @Param annotation kinds :

  • @HeaderParam("foo"), aliasing @Param(value="foo", kind=Kind.HEADER)
  • @QueryParam("foo"), aliasing @Param(value="foo", kind=Kind.QUERY)
  • @PathParam("foo"), aliasing @Param(value="foo", kind=Kind.PATH)
  • @ContextParam("request"), aliasing @Param(value="request", kind=Kind.CONTEXT)

Producing endpoint annotations metadata and making it available at runtime

Annotations attached to any @RestxResource endpoint will be transposed to OperationDescription.annotations new field attached to target endpoint.

This opens a lot of possibilities as the OperationDescription.annotations will be retrievable at runtime as soon as you have an StdEntityRoute instance in hand, typically in RestxFilters.

It would allow to create any custom endpoint annotation, specific to your project, and implement your own custom behaviour around this custom annotation in a custom RestxFilter.

An EntityRelatedFilter useful superclass has been provided to help implementing such RestxFilter with some commodity. You can have a look at ExpiresHeaderFilter or LocationHeaderFilter for examples on such Filter implementations.

@ExpiresAfter and @LocationHeader new annotations, and injecting RestxResponse

2 new annotations have been added to manage some frequently used response headers. Those annotations handling are using the new OperationDescription.annotations field we talked about above and are aimed at giving you some examples if you decide to implement your own Response Headers management.

@ExpiresAfter annotation allows to generate an Expires response header. It can be used this way :

    @GET("/expires")
    @ExpiresAfter("2d 4h")
    public String expireHeader() {
        return "hello";
    }

@LocationHeader annotation allows to generate a Location response header. It can interpolate fields from entity returned by your endpoint, and can use special _baseUri_ and _currentUri_ variables. It can be used this way :

    @POST("/foos")
    @LocationHeader("{_currentUri_}/{id}") // Resolved to /api/foos/{id}
    public Foo locationHeader(Foo foo) {
        foo.setId("123456");
        return foo;
    }

    @POST("/foos2")
    @LocationHeader("{_baseUri_}/headers/foos2/{id}") // Resolved to /api/headers/foos2/{id}
    public Foo locationHeader2(Foo foo) {
        foo.setId("123456");
        return foo;
    }

In the end, for easy custom response header management, you will be able to inject RestxResponse into your enpoints by using @Param(value="response", kind=Kind.CONTEXT) special annotation. This behaviour is clearly discouraged for several reasons :

  • you’re tainting your endpoint with Restx specific API (like you would do with RestxRequest)
  • things you will do with RestxResponse instance will remain undocumented in api-docs
  • with great powers comes great responsibilities : if you use RestxResponse API to write response body too early, it may lead to unwanted/unpredictable behaviour.

CORE

  • 52c625f improved ConfigLoader which can now load settings from a file on the filesystem (see documentation).
  • 2994692 introduced CurrentLocaleResolver component used to provide your own locale guessing in MessagesRouter, particularly in cases when locale is part of User’s data
  • ba28876 introduced PermissionFactory component allowing to provide your own hasRole() implementation, and replacing Permissions utility class.
  • 316c3f4 introduced SessionInvalider component providing extension point to custom logout behaviours
  • 99acd3d introduced CurrentSessionResolver component allowing to provide your own current session resolution on GET /sessions/current calls
  • 46f8b58 principal cache is cleared upon logout, thus allowing to refresh principal roles on his next connection
  • e6e5edd better ResourcesRoute example in doc as the previous one was suggesting a security flaw
  • 6529fad introduced domain & secure flags on RestxSessionCookieDescriptor allowing to further customize generated cookies; old behaviour (no domain, secure=false) is kept by default.
  • 4c139a7 allowing underscores in path param names
  • 6ce644f showing explicit error log when detecting DI cycle (see 682fb8a)
  • e61bcf2 endpoints can now throw checked exceptions not extending IOException.

VALIDATION

  • bb91412 introduced MethodArgumentNotValidException wrapping bean-validation violations, useful if you want to send it to the client.

I18N

  • 0576682 caching resolved Messages key for a given Locale

MONGO

  • e980981 introduced new restx-jongo-java8 artefact for java8 datetime serialization support with jongo.

BUILD

  • 3421e31 on srv/ui projects, not having dependency from srv to ui anymore, except during release profile
  • e85b0f6 introduced !optional flag in md.restx.json descriptor allowing to declare some dependencies as optional

REFACTORS

SHELL

  • 15e874d falling back on maven deps installation when no md.restx.json is found in current module
  • 95d5e6c falling back on ivy deps installation when no md.restx.json file nor pom.xml file is found in current module
  • e1d2202 allowing to generate md.restx.json only, pom.xml only or module.ivy only when calling restx app new
  • dc2e0f2 fixing pom.xml parsing when some artefact GAV properties are inherited from parent artefact
  • ef85173 keeping parsed representation of module descriptors (pom.xml, restx.md.json etc..) in order to use those parsed representations when writing updated representation of the descriptor
  • dca208d chrooting on srv/ sub-directory when restx app run command is launched from a directory not containing any md.restx.json file
  • 85539e4 returning back on initial shell location after restx app run
  • 6b1334d falling back on ivy-based pom.xml dependency resolution when we detect mvn command is not installed on current machine
  • 19c1aef moved restx shell modules into a new dedicated restx-shell repository as restx and restx-shell should not have the same lifecycle

API Docs

  • fcb821d removing api-docs relatedOperations when targetting String type as it was leading to a lot of useless related operations.

SERVERS

  • e77f848 replaced restx-server-simple by restx-server-jetty8 in samplest, making debugging easier as restx-server-simple doesn’t propagate exceptions occuring during route processing.
  • 934f931 95ed631 introduced new restx-server-jetty7 artefact for servlet 2.5-compatible embedded jetty server
  • 6b20ac6 introduced WebServerBase superclass intended to share common WebServer code
  • ad67870 allowing to specify bind interface on SimpleWebServer’s builder

MINOR

  • b54562c Introduced MoreClasses.getInheritedClasses() utility method
  • c41aeda Added example of i18n-admin module in samplest
  • dee37c8 adds toString on generated ParameterizedType to ease debugging
  • 6a56329 lowered factory log level from INFO to DEBUG for less verbose output in factories
  • 98d8528 introduced MoreAnnotations utility class

BUG FIXES

  • c41aeda i18n admin module doesn’t give access to messages (Fixes #179)
  • b5bbb99 make MongoClient an AutoCloseable component (Fixes #193)
  • be01892 fix: exception when watcher services are closed
  • 51982bb fix: two generated ParameterizedTypes were not equals
  • 8a75daa considering restx-server dependency as optional on new restx projects to remove it (and its dependencies) from packaging (Fixes #220)
  • 8cbcaaf mark servlet-api dependency as provided
  • 418811f e0e01e5 (security) all requests to admin endpoints needs restx-admin role
  • fce9d8d (security) 404 response should not list every endpoints in prod mode
  • 449b870 DELETE endpoint parameters should be looked up in QUERY param instead of BODY content when no @Param is provided (default behaviour)
  • b4d8650 fixing int underflow issue when comparing engines or names having priority set to Integer.MAX_VALUE (Fixes #242)
  • 877744c allowing backslashes in restx configs, allowing multiline property value (Fixes #196)
  • b9d5e2b fix specs recording on root url endpoint (/) (Fixes #176)
  • f061e73 handling EOF (ctrl+D) in restx shell (Fixes #200)
  • 55226db when provided, query/path param name defined in annotation value should prevail over variable name in resource
  • 6e337b4 fixed type descriptions in api docs on complex parameterized types (generics)
  • 8c3b781 PATH parameters are not url-encoded anymore in restx console (Fixes #257)

Getting started / Upgrading

Want to get started now? Check out the related doc.

Upgrading from an earlier version?

  • in your projects you just need to update restx.version to 0.35 in your dependency descriptor
  • in your code you might have to adapt to some breaking changes (see below)
  • in the shell, run shell upgrade to upgrade your shell and plugins.

MAJOR BREAKING CHANGES

Those breaking are likely to be hit by any existing RestX project. Consider those as a “migration guide” to apply on your project :

  • 9a93edf restx-server-jetty artefact has been renamed to restx-server-jetty8
  • 8475ee5 renamed JettyWebServer to Jetty8WebServer, same for module and properties (for instance, restx.server.jetty.webxml.default.location => restx.server.jetty8.webxml.default.location)
  • ba28876 Permissions utility class has been replaced by PermissionFactory component
  • ba28876 StdRestxSecurityManager now takes a PermissionFactory in its constructor, if you subclassed it, you will need to provide this component during construction (simply inject it in your constructor).
  • ebac25e PATH params are url-decoded by default; if you want to keep old behaviour, simply @Provide @Named("restx.http.decode.url.path.params") component valued to false
  • Some libraries have evolved :
    • 2bab182 upgraded guava from 17.0 to 18.0. See guava 18 release note.
    • 9e56b1f upgraded jongo from 1.0 to 1.3.0. See jongo release note. Worth noting in this upgrade is the compatibility with mongo-java-driver 3.0 and the rename of some frequently used annotations : @Id => @MongoId and @ObjectId => @MongoObjectId
      Important : upgrade has been rolled back to jongo 1.1 in 0.35.1, upgrade to jongo 1.4.0 has been postponed to 0.36.
    • 1c07f87 b1c4dd5 following jongo upgrade to 1.3.0, mongo-java-driver has been upgraded to 3.4 (see compatibility matrix) and bson4jackson to 2.8.0.
      Important : those upgrades have been rolled back in 0.35.1, upgrade to mongo-java-driver 3.4.0 & bson4jackson 2.9.0 have been postponed to 0.36.
    • 515d8e8 upgraded jackson from 2.3.3 to 2.8.10 (latest 2.8.X version). See jackson release notes.
  • If you implemented your own routes :
    • 58f190a RestxRequestMatcher should be passed to RestxSecurityManager
    • 4f61fd2 considering a StdEntityRoute should always bring a permissionFactory at construction time (simply inject it in your route and pass it to the super constructor)
    • PR #177 StdEntityRoute constructor and input parameters mapping have evolved (have a look at the Unified and improved Query, Path and Body params handling section)
  • If you implemented your own WebServer :
    • f24469d removed serverId useless field in both constructor and builder
    • 8f58414 TomcatWebServer constructor now takes a bind interface
  • 46f8b58 principal cached roles are now cleared upon logout; if you already were cleaning the roles, don’t forget to remove this behaviour or implement your own SessionInvalider component for this purpose
  • 8c14dff GET /sessions/current returns 404 Not found instead of 200 OK when no session is defined for current request
  • 3db7d18 every graphite settings are now prefixed with restx. to avoid collisions with existing graphite properties potentially defined on your app server

MINOR BREAKING CHANGES

Those breaking changes are unlikely to happen as it is happening on very rare/specific cases.

Anyway, this is worth noting it in case you would be in those particular scenario :

  • 460715b Name are a String+Type instead of a String+Class
  • ceb7a5b FactoryMachine.nameBuildableComponents uses Type (instead of Class)
  • 58f190a if you implemented your own RestxSecurityManager, you will have to update check() prototype to take a RestxRequestMatcher
  • f3e51cf if you implemented your own Permission implementation, you will have to update has() prototype to take a Map<String, String> roleInterpolationMap parameter
  • f3e51cf if you relied on Permissions utility class, you will have to pass an additionnal Map<String, String> roleInterpolationMap parameter to method calls
  • 44e142c if you were using braces ({}) in your roles, those will now be interpolated
  • 2afa00b if you provided your own Messages implementation, you will have to provide an Iterable<String> keys(Locale) with same impl than Iterable<String> keys()
  • 0576682 if you provided your own MutableMessages implementation, don’t forget to invalidate cached keys when you mutate your MutableMessages instance (most of the time in setMessageTemplate())
  • 9effdfd ResourcesRoute doesn’t allow to serve resources from root classpath anymore, as it is considered a security flaw
  • 489961d using static classes for shell’s deps command’s subcommands instead of instance classes
  • 449b870 DELETE endpoint parameters should be looked up in QUERY param instead of BODY content when no @Param is provided (default behaviour)

Contributions

Thanks a lot to the community who made this possible, especially the contributors to this release:

comments powered by Disqus