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 asAutoStartable
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 andPath
parameters can now beOptional
- as before, non-
Optional
parameters are implicitely mandatory, no matter its parameter type
For the internals, parameters deserialization are now handled by dedicated @Component
s 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
:
BaseTypeEndpointParameterMapper
: mapper used to handleBaseType
which may be handled byMainStringConverter
(jackson-based) componentBaseTypeAggregateEndpointParameterMapper
: mapper used to handle anAggregate
ofBaseType
s. SupportedAggregate
s for this release areIterable
,List
,Set
,Collection
andArray
ComplexTypeEndpointParameterMapper
: mapper used to handle complex (POJO) types. However, this component is not implemented yet (we’ll keep this implementation for next RestX release, see #248)
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 ofParamDef
s inStdEntityRoute
’s constructor thoseParamDef
attributes represent parameter metadata used byEndpointParameterMapperFactory
to guessEndpointParameterMapper
. - 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 RestxFilter
s.
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 writeresponse
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 inMessagesRouter
, particularly in cases when locale is part of User’s data - ba28876 introduced
PermissionFactory
component allowing to provide your ownhasRole()
implementation, and replacingPermissions
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 onGET /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 onRestxSessionCookieDescriptor
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 givenLocale
MONGO
- e980981 introduced new
restx-jongo-java8
artefact forjava8
datetime serialization support withjongo
.
BUILD
- 3421e31 on srv/ui projects, not having dependency from srv to ui
anymore, except during
release
profile - e85b0f6 introduced
!optional
flag inmd.restx.json
descriptor allowing to declare some dependencies as optional
REFACTORS
- 2b3dc2a make RestxAnnotationProcessor reusable for different annotations
- 424bedc 34822ee
7389683 16a4951
better
ResourcesRoute
extensibility
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 whenrestx app run
command is launched from a directory not containing anymd.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 detectmvn
command is not installed on current machine - 19c1aef moved
restx shell
modules into a new dedicatedrestx-shell
repository asrestx
andrestx-shell
should not have the same lifecycle
API Docs
- fcb821d removing api-docs
relatedOperations
when targettingString
type as it was leading to a lot of useless related operations.
SERVERS
- e77f848 replaced
restx-server-simple
byrestx-server-jetty8
insamplest
, making debugging easier asrestx-server-simple
doesn’t propagate exceptions occuring during route processing. - 934f931 95ed631 introduced
new
restx-server-jetty7
artefact forservlet 2.5
-compatible embedded jetty server - 6b20ac6 introduced
WebServerBase
superclass intended to share commonWebServer
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 inQUERY
param instead ofBODY
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 torestx-server-jetty8
- 8475ee5 renamed
JettyWebServer
toJetty8WebServer
, 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 byPermissionFactory
component - ba28876
StdRestxSecurityManager
now takes aPermissionFactory
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 tofalse
- 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 to3.4
(see compatibility matrix) andbson4jackson
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 toRestxSecurityManager
- 4f61fd2 considering a
StdEntityRoute
should always bring apermissionFactory
at construction time (simply inject it in your route and pass it to thesuper
constructor) - PR #177
StdEntityRoute
constructor and input parameters mapping have evolved (have a look at theUnified and improved Query, Path and Body params handling
section)
- 58f190a
- If you implemented your own
WebServer
: - 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
returns404 Not found
instead of200 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 aString+Type
instead of aString+Class
- ceb7a5b
FactoryMachine.nameBuildableComponents
usesType
(instead ofClass
) - 58f190a if you implemented your own
RestxSecurityManager
, you will have to updatecheck()
prototype to take aRestxRequestMatcher
- f3e51cf if you implemented your own
Permission
implementation, you will have to updatehas()
prototype to take aMap<String, String> roleInterpolationMap
parameter - f3e51cf if you relied on
Permissions
utility class, you will have to pass an additionnalMap<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 anIterable<String> keys(Locale)
with same impl thanIterable<String> keys()
- 0576682 if you provided your own
MutableMessages
implementation, don’t forget to invalidate cached keys when you mutate yourMutableMessages
instance (most of the time insetMessageTemplate()
) - 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 inQUERY
param instead ofBODY
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:
- Xavier Hanin (committer),
- Frédéric Camblor (committer)
- Augustin Peyrard (committer)
- Cedric Gatay
- Thomas Zayouna
- David Pilato
- Julien Legras & Synacktiv for their security advisory