Release 7.2.0
Date: Sept 25, 2018
7.2.0 is a major release that introduces several significant new features:
- OpenAPI part serializing and parsing with full support for OpenAPI validation of input and output in the REST servlet and client APIs.
- Swagger UI.
- New HTTP-Part annotations that are applicable to both the servlet and client APIs.
- Serverless servlet and client unit testing.
- Simplified UI customization.
- Marshalls that combines serializers and parsers into a single API.
juneau-marshall
-
The REST client
@Remoteable
annotations and REST server@RemoteMethod
annotations which used to be in separate packages in the client and server projects have been combined into a single set of annotations in the org.apache.juneau.http.annotation package. This fixes a long-standing problem where it was easy to mix up using client-side annotations in server-side code, and vis-versa. Additionally, much work has been done on these annotations to add support for Swagger-style validations and documentation.HTTP Part Annotations: @BodyFormData Header Path Query HasFormData HasQuery Request These are used with new Swagger schema/documentation annotations to produce schema-based serialization/parsing/validation and auto-generated Swagger documentation:
Swagger Schema Annotations: Contact ExternalDocsItemsLicense SchemaSubItemsTagAdditionally, the
@Remoteable
annotation has been split into the following two annotations:@RemoteInterface- Used for remote proxy interfaces served up throughRemoteInterfaceServletor REST"PROXY"
methods. Defaults to"POST"
with method signatures as paths.@RemoteResource- Used for 3rd-party REST interfaces. Defaults to"GET"
with standardized naming conventions for paths.
-
Support for multi-valued parameters as maps or beans on server-side annotations (it was previously supported on client-side):
@Query("*")
,@FormData("*")
,@Header("*")
,@Path("*")
-
Support for server-side use of
@Request
annotation on@RestMethod
annotations and new RestRequest.getRequest(RequestBeanMeta) method. -
Fixed bug where
@Bean(typeName)
was not being detected on non-bean POJO classes. -
Fixed bug where HTML-Schema was not being rendered correctly.
-
Support for POJO examples:
BeanContext.BEAN_examples@Example -
Fixed bug where parsers could report the wrong line number when an error occurred.
-
A runtime exception is now thrown if you define a
@BeanProperty(name)but forget to add it to your@Bean(properties)
annotation. -
@Html(asXml)
and@Html(asPlainText)
replaced with @Html(format). -
HTML serializer will now serializers beans and maps as HTML even when those objects are embedded within an object with
@Html(format=XML)
. The previous behavior was to serialize it as XML. -
New settings for binary-based serializers and parsers:
OutputStreamSerializer.OSSERIALIZER_binaryFormatInputStreamParser.ISPARSER_binaryFormat -
Added support for auto-detection of fluent-style setters:
BeanContext.BEAN_fluentSettersBean.fluentSetters() -
The
SERIALIZER_abridged
setting has been replaced withSerializer.SERIALIZER_addRootType -
The
SERIALIZER_addBeanTypeProperties
setting has been replaced withSerializer.SERIALIZER_addBeanTypesand is disabled by default. -
Parse exception messages are now clearer and include code snippets of where a parse exception occurred:
org.apache.juneau.parser.ParseException: Expected '[' at beginning of JSON array.
At line 80, column 20.
While parsing into:
currentClass: List<String>
currentProperty: required: java.util.List, field=[null], getter=[public java.util.List org.apache.juneau.dto.swagger.SchemaInfo.getRequired()], setter=[public org.apache.juneau.dto.swagger.SchemaInfo org.apache.juneau.dto.swagger.SchemaInfo.setRequired(java.util.Collection)]
---start--
0075: "name": "body",
0076: "description": "Pet object that needs to be added to the store",
0077: "required": true,
0078: "schema": {
0079: "required": true,
0080: }
0081: }
0082: ],
0083: "responses": {
0084: "405": {
0085: "description": "Invalid input"
---end--- -
New property
Parser.PARSER_debugOutputLinesfor controlling how many input lines are added to the exception message above. -
New property
BeanContext.BEAN_useEnumNamesfor controlling whether enums are serialized using their name or thetoString()
method. -
New property
BeanContext.BEAN_examplesfor defining examples of POJOs. -
New @Example annotation for defining examples of POJOs. Used heavily in JSON-Schema support.
-
If a bean has both a
getX()
andisX()
method, thegetX()
method takes precedence. The previous behavior was arbitrary. -
Significant improvements to JSON-Schema serialization support.
- New
@JsonSchemaannotation.
- New
-
Fixed
NullPointerException
when serializing beans with a dyna-property (i.e.@Bean("*")
) which returns anull
value. -
New option for dyna-property (i.e.
@Bean("*")
) using a method that returns a collection of extra keys. See new options #4 onBeanProperty.name() -
New formats for the @Html(format) annotation:
- Format collections as comma-delimited lists.HtmlFormat.HTML_CDC - Format collections as space-delimited lists.HtmlFormat.HTML_SDC -
Serializers now allow for q-values on the media types they handle. For example, the accept media type on
JsonSerializer.Simple
is"application/json+simple,application/json;q=0.9"
. This means the serializer CAN handle requests for"application/json"
if no other serializers provide a better match. -
New methods for creating unmodifiable
ObjectMapsandObjectLists.ObjectMapObjectMap.isUnmodifiable()ObjectMap.unmodifiable()ObjectMap.modifiable()ObjectListObjectList.isUnmodifiable()ObjectList.unmodifiable()ObjectList.modifiable() -
The
JsonSerializer.Simple
class has been moved into the top-levelSimpleJsonSerializerclass. -
RDF serializer subclasses have been moved into top-level classes:
RdfSerializer.Xml
→RdfXmlSerializerRdfSerializer.XmlAbbrev
→RdfXmlAbbrevSerializerRdfSerializer.N3
→N3SerializerRdfSerializer.NTriple
→NTripleSerializerRdfSerializer.Turtle
→TurtleSerializerRdfParser.Xml
→RdfXmlParserRdfParser.N3
→N3ParserRdfParser.NTriple
→NTripleParserRdfParser.Turtle
→TurtleParser
-
New API for pairing serializers and parsers for simplified syntax:
Examples:
// Using instance.
Json json = new Json();
MyPojo myPojo = json.read(string, MyPojo.class);
String string = json.write(myPojo);// Using DEFAULT instance.
MyPojo myPojo = Json.DEFAULT.read(string, MyPojo.class);
String string = Json.DEFAULT.write(myPojo);MarshallCharMarshallHtmlJsonPlainTextSimpleJsonUonUrlEncodingXmlN3NTripleRdfXmlRdfXmlAbbrevTurtleStreamMarshallJsoMsgPack -
New/updated documentation:
2.15.3 - Simplified JSON
juneau-dto
-
Fixed bug where Swagger
SchemaInfo.required(Object...)was defined as a boolean instead of a list of strings. -
Boolean attributes are now handled correctly for HTML5. For example, calling
new Select().disabled(true)
will produce<select disabled='disabled'>
juneau-rest-server
-
Auto-generated
Swagger UI. -
Simplified
@RestResource(swagger)and@RestMethod(swagger)annotations. -
Fixed bug in
UriResolver
when request path info had special characters. -
Fixed bug where incorrect media type was being set on responses (e.g.
text/html+schema
instead oftext/html
for schema documents). -
The
RemoteableServlet
class has been moved and renamed toRemoteInterfaceServlet. -
RemoteInterfaceServletnow provides a form page for invoking remote interface methods in a browser. -
Newlines were being stripped from
@HtmlDoc(script)
when serialized which could cause script lines to become commented out. -
New @Response annotation that can be applied to throwables thrown from REST methods and POJOs returned by REST methods to specify non-200 status return codes and descriptions in Swagger documentation.
-
Swagger fields added to the following annotations:
HTTP Part Annotations with Swagger Support: @BodyFormData Header Path Query -
The
@PathRemainder
annotation has been removed entirely. Use@Path("/*")
to access the path remainder which includes all the new OpenAPI parsing support. -
"Helper" classes (i.e. reusable beans that can be returned by REST methods) have been moved to the following package with some new additions:
org.apache.juneau.rest.helperBeanDescriptionChildResourceDescriptionsReaderResourceReaderResourceBuilderSeeOtherRootResourceDescriptionStreamResourceStreamResourceBuilder -
Predefined HTTP responses.
org.apache.juneau.rest.responseAcceptedAlreadyReportedContinueCreatedEarlyHintsFoundIMUsedMovedPermanentlyMultipleChoicesMultiStatusNoContentNonAuthoritiveInformationNotModifiedOkPartialContentPermanentRedirectProcessingResetContentSeeOtherSwitchingProtocolsTemporaryRedirectUseProxy -
Predefined HTTP error throwables. When added to REST Java methods, reflected in generated Swagger documentation.
org.apache.juneau.rest.exceptionBadRequestConflictExpectationFailedFailedDependencyForbiddenGoneHttpVersionNotSupportedInsufficientStorageInternalServerErrorLengthRequiredLockedLoopDetectedMethodNotAllowedMisdirectedRequestNetworkAuthenticationRequiredNotAcceptableNotExtendedNotFoundNotImplementedPayloadTooLargePreconditionFailedPreconditionRequiredRangeNotSatisfiableRequestHeaderFieldsTooLargeServiceUnavailableTooManyRequestsUnauthorizedUnavailableForLegalReasonsUnprocessableEntityUnsupportedMediaTypeUpgradeRequiredUriTooLongVariantAlsoNegotiates -
The
@HtmlDoc(nav)and@HtmlDoc(navlinks)can now both be used on the same annotation. The contents ofnav()
are free-form HTML that gets rendered immediately after the navigation links. -
The following new parameter types can be used on REST methods:
ReaderParser - The reader parser matching the request content type.InputStreamParser - The input stream parser matching the request content type. -
The
$F
variable can now be used as a initialization time variable. For example, theAtomFeedResource
example pulls a bean example from a file on the classpath:@RestResource(
path="/atom",
title="Sample ATOM feed resource",
properties={
@Property(name=BEAN_examples, value="{'org.apache.juneau.dto.atom.Feed': $F{AtomFeedResource_example.json}}")
},
...
)It should be noted that you cannot use the
$F
variable to retrieve localized versions of files (since you're not within the scope of a client request. -
The
RestResource.nowrap()annotation has been changed to a string with a default value of"true"
. Having it as a string allows us to differentiate between a set and unset value so that it can be overridden in subclasses. -
The @Path.name() annotation parameter is now required.
-
New class for mock unit testing of REST resources:
MockRest -
@RestMethod(inherit)
annotation has been removed and replaced with the following classes:Inheritance Control Classes: InheritNoneThese can be used in the following locations:
@RestResource.serializers()@RestResource.parsers()@RestResource.beanFilters()@RestResource.pojoSwaps()@RestMethod.serializers()@RestMethod.parsers()@RestMethod.beanFilters()@RestMethod.pojoSwaps()One advantage is that you now have control over the precedence of serializers and parsers by where you insert the
Inherit
class. -
RequestPathMatch
class has been renamed toRequestPath. -
@Request objects can now be used as parameters in
@RestMethod
methods. Includes new methods on RestRequest:getRequest(Class) getRequest(RequestBeanMeta) -
New methods added to MenuItemWidget to allow population of menu item content using Javascript and Ajax calls:
MenuItemWidget getBeforeShowScript(RestRequest)getAfterShowScript(RestRequest) -
New methods added to Widget to allow retrieving classpath resources with embedded SVL variables:
Widget loadHtmlWithVars(RestRequest,String)loadScriptWithVars(RestRequest,String)loadStyleWithVars(RestRequest,String) -
New/updated documentation:
juneau-rest-server.UnitTesting -
The behavior of the default values for
RestMethod.name()andRestMethod.path()have changed. If not specified, the values are inferred from the Java method name. See Also:RestMethod -
RedirectToServletRoot
class has been renamed toSeeOtherRoot. -
New REST context settings:
RestContext RestContext.REST_uriAuthorityRestContext.REST_uriContextRestContext.REST_uriRelativityRestContext.REST_uriResolution -
New convenience annotations for specifying default
Accept
andContent-Type
headers:@RestResourcedefaultAcceptdefaultContentType@RestMethodRestMethod.defaultAcceptRestMethod.defaultContentType
juneau-rest-client
-
Remote Resource interfaces support OpenAPI annotations.
-
Made improvements to the builder API for defining SSL support. New methods added:
RestClient.Builder RestClient.Builder.sslProtocols(String...)RestClient.Builder.cipherSuites(String...)Builder.hostnameVerifier(HostnameVerifier)RestClient.Builder.keyManagers(KeyManager...)RestClient.Builder.trustManagers(TrustManager...)Builder.secureRandom(SecureRandom)Builder.httpClientConnectionManager(HttpClientConnectionManager) -
Clients no longer have JSON defined as the default serializer and parser. Instead, the clients can now be used with no serializer/parser if you're working with InputStreams/Readers or POJOs that can be converted to Strings and converted from Strings/InputStreams/Readers.
-
Methods added to client builder to make it easy to define the transport language:
RestClient.Builder json() xml() html() uon() urlEnc() msgPack() plainText() -
New method added for allowing serverless client testing against REST interfaces.
RestClient.Builder mockHttpConnection(MockHttpConnection) -
Removed the deprecated
RestCall.execute()
method. UseRestCall.run(). -
RestCall.input(Object)
method renamed toRestCall.body(Object)to match OpenAPI terminology. -
Made constructors on RestClient and RestClient.Builder protected so that they can be subclassed.
-
The
RestClient.getRemoteableProxy()
methods have been split into separate methods for Remote Interfaces and Remote Resources:RestClient RestClient.getRemoteInterface(Class)RestClient.getRemoteInterface(Class,Object)RestClient.getRemoteInterface(Class,Object,Serializer,Parser)RestClient.getRemoteResource(Class)RestClient.getRemoteResource(Class,Object)RestClient.getRemoteResource(Class,Object,Serializer,Parser)
juneau-rest-microservice
-
The look-and-feel of an application is now controlled through the external configuration file and access to CSS stylesheets in the working directory in a new folder called
files
:The default configuration is this:
#=======================================================================================================================
# REST settings
#=======================================================================================================================
[REST]
staticFiles = htdocs:files/htdocs
# Stylesheet to use for HTML views.
theme = servlet:/htdocs/themes/devops.css
headerIcon = servlet:/htdocs/images/juneau.png
headerLink = http://juneau.apache.org
footerIcon = servlet:/htdocs/images/asf.png
footerLink = http://www.apache.org
icon = $C{REST/headerIcon}
header = <a href='$U{$C{REST/headerLink}}'><img src='$U{$C{REST/headerIcon}}' style='position:absolute;top:5;right:5;background-color:transparent;height:30px'/></a>
footer = <a href='$U{$C{REST/footerLink}}'><img style='float:right;padding-right:20px;height:32px' src='$U{$C{REST/footerIcon}}'>Note that static files can now be served up from the
files
directory in the working directory, and you have access to modify the CSS theme files. TheSwaggerUI.css
file controls the look-and-feel of the Swagger UI, so you can make modification there as well.The
BasicRestConfig
interface (which defines the default settings for theBasicRestServlet
class) now looks like this...@RestResource(
...
htmldoc=@HtmlDoc(
header={
"<h1>$R{resourceTitle}</h1>",
"<h2>$R{methodSummary,resourceDescription}</h2>",
"$C{REST/header}"
},
navlinks={
"up: request:/.."
},
stylesheet="$C{REST/theme,servlet:/htdocs/themes/devops.css}",
head={
"<link rel='icon' href='$U{$C{REST/icon}}'/>"
},
footer="$C{REST/footer}"
),
// These are static files that are served up by the servlet under the specified sub-paths.
// For example, "/servletPath/htdocs/javadoc.css" resolves to the file "[servlet-package]/htdocs/javadoc.css"
staticFiles={"$C{REST/staticFiles}"}
)
public interface BasicRestConfig {}The
PoweredByApache
widget which used to serve as a page footer has been eliminated.If you're testing out changes in the theme stylesheets, you may want to set the following system property that prevents caching of those files so that you don't need to restart the microservice each time a change is made:
#=======================================================================================================================
# System properties
#=======================================================================================================================
[SystemProperties]
# Disable classpath resource caching.
# Useful if you're attached using a debugger and you're modifying classpath resources while running.
RestContext.useClasspathResourceCaching.b = false -
Upgraded to Jetty 9.4.12.