8.2.0 (Oct 14, 2020)

Juneau 8.2.0 is a major release. The most significant change is the addition of an entirely new RestClient API build from scratch with near 100% unit test coverage. The new API is located in the org.apache.juneau.rest.client2 package and will replace the old API in 9.0.

##### juneau-marshall

- {@link oaj.annotation.Bean @Bean} and {@link oaj.annotation.BeanIgnore @BeanIgnore} annotations can alternately occur in parent class hierarchy. The first one found dictates whether a class is ignored as a bean or not.
- Applying the {@link oaj.annotation.Bean @Bean} annotation on a class will now force non-public classes to be interpreted as beans. For example, applying {@link oaj.annotation.Bean @Bean} to a private class will force it to be treated as a bean.
  Also, if a public bean constructor cannot be found, the default constructor will be used regardless of it's visibility if the {@link oaj.annotation.Bean @Bean} annotation is on the class.
- The @Beanc annotation can now be recognized and used on non-public constructors.
- Annotations are now aggregated across the entire class hierarchy instead of simply being overridden.
  The following is an example.

  // Parent class with properties a,b,c @Bean(bpi="a,b,c") public class MyClass { public int a, b, c, d; } // New behavior: Child class with properties a,c because @Beans are aggregated. // Old behavior: Child class with properties a,c,d because @Bean is overridden. @Bean(bpx="b") public class MyClass { public int a, b, c, d; }

- Include/exclude/read-only/write-only properties defined on the bean context now override those defined on annotations of the class itself. For example, the following methods override the {@link oaj.annotation.Bean @Bean} annotations on classes:
  - {@link oaj.BeanContext.Builder}
    - Builder.bpi(Class,String) bpi(Class,String)
    - Builder.bpi(String,String) bpi(String,String)
    - Builder.bpx(Class,String) bpx(Class,String)
    - Builder.bpx(String,String) bpx(String,String)
    - Builder.bpro(Class,String) bpro(Class,String)
    - Builder.bpro(String,String) bpro(String,String)
    - Builder.bpwo(Class,String) bpwo(Class,String
    - Builder.bpwo(String,String) bpwo(String,String
- Config annotations now override class-level annotations.
  For example, only the 'a' and 'b' properties get serialized on the bean below:

  // Parent class with properties a,b,c @Bean(bpi="a,b,c") public class MyClass { public int a, b, c, d; } @RestMethod @BeanConfig(beanApply={@Bean(on="MyClass",bpi="a,b")} public MyClass getMyClass() {...}

- The following concrete annotation implementation classes are now provided that can be used with the {@link oaj.BeanContext.Builder#annotations(Annotation...)} method:
  - {@link oaj.annotation.BeanAnnotation} implements {@link oaj.annotation.Bean}
  - {@link oaj.annotation.BeancAnnotation} implements {@link oaj.annotation.Beanc}
  - {@link oaj.annotation.BeanIgnoreAnnotation} implements {@link oaj.annotation.BeanIgnore}
  - {@link oaj.annotation.BeanpAnnotation} implements {@link oaj.annotation.Beanp}
  - {@link oaj.annotation.ExampleAnnotation} implements {@link oaj.annotation.Example}
  - {@link oaj.annotation.NamePropertyAnnotation} implements {@link oaj.annotation.NameProperty}
  - {@link oaj.annotation.ParentPropertyAnnotation} implements {@link oaj.annotation.ParentProperty}
  - {@link oaj.annotation.SwapAnnotation} implements {@link oaj.annotation.Swap}
  - {@link oaj.annotation.UriAnnotation} implements URI
  - {@link oaj.csv.annotation.CsvAnnotation} implements {@link oaj.csv.annotation.Csv}
  - {@link oaj.html.annotation.HtmlAnnotation} implements {@link oaj.html.annotation.Html}
  - JsoAnnotation implements Jso
  - {@link oaj.json.annotation.JsonAnnotation} implements {@link oaj.json.annotation.Json}
  - SchemaAnnotation implements Schema
  - {@link oaj.msgpack.annotation.MsgPackAnnotation} implements {@link oaj.msgpack.annotation.MsgPack}
  - {@link oaj.oapi.annotation.OpenApiAnnotation} implements {@link oaj.oapi.annotation.OpenApi}
  - {@link oaj.plaintext.annotation.PlainTextAnnotation} implements {@link oaj.plaintext.annotation.PlainText}
  - {@link oaj.soap.annotation.SoapXmlAnnotation} implements {@link oaj.soap.annotation.SoapXml}
  - {@link oaj.uon.annotation.UonAnnotation} implements {@link oaj.uon.annotation.Uon}
  - {@link oaj.urlencoding.annotation.UrlEncodingAnnotation} implements {@link oaj.urlencoding.annotation.UrlEncoding}
  - {@link oaj.xml.annotation.XmlAnnotation} implements {@link oaj.xml.annotation.Xml}
  Example:

  @Bean(bpi="street,city") // Will be overridden public class AddressBean {...} Bean ba = new BeanAnnotation("AddressBean").bpi("street,city,state"); WriterSerializer ws = JsonSerializer. create().annotations(ba).build(); String json = ws.toString(addressBean); // Will print street,city,state

- Bean maps now have the concept of "hidden" properties (properties that aren't serialized but otherwise accessible).
  For example, the {@link oaj.html.annotation.Html#link()} can now reference hidden properties:

  @Bean(bpi="a") // Will be overridden public class MyBean { @Html(link="servlet:/{b}") public String a; public String b; // Not serialized but referenced in link on a. }

  The general rule for the {@link oaj.BeanMap} class is that get(),put(), and containsKey() will work against hidden properties but keySet() and entrySet() will skip them.
- Several bug fixes in the {@link oaj.html.HtmlSerializer} and {@link oaj.html.HtmlParser} classes around the handling of collections and arrays of beans with @Bean(typeName) annotations.
- New swaps auto-added to all serializers/parsers:
  - MatchResultSwap
  - StackTraceElementSwap
- {@link oaj.html.annotation.Html#noTableHeaders} now can be applied to collections of beans.
- New {@link oaj.html.annotation.HtmlDocConfig#asideFloat()} setting so that you can position the contents of the aside section on the page.
- Various minor fixes surrounding HTML serialization.
  - Collections of beans that were supposed to be serialized as tables were being serialized as lists.
  - Collections of beans with @Bean(bpi) were not being serialized in the correct column order.
- Fixed a bug where a copy constructor can erroneously be recognized as a builder constructor if the class also has a static create method. Net effect was that the copy constructor would needlessly be called during parsing.
- New {@link oaj.collections} package containing various convenience fluent-style collection classes:
  - AList
  - ASet
  - ASortedSet
  - AMap
  - ASortedMap
  - OMap
  - OList
- ObjectMap is being deprecated and replaced with OMap.
- ObjectList is being deprecated and replaced with OList.
- All classes in the {@link oaj.http.response} and exception now have header(String,Object) methods for adding response headers.

  // Method that performs a BASIC Auth handshake. @RestMethod public Ok checkBasicAuth(@Header("Authorization") String auth) throws Unauthorized { if (auth == null) throw new Unauthorized().header("WWW-Authenticate", "BASIC realm=\"foo\""); return Ok. OK; }

- New annotations for multi-part support:
  - Header.multi()
  - Query.multi()
  - FormData.multi()
- BeanTraverseContext.BEANTRAVERSE_ignoreRecursionssetting no longer requires BeanTraverseContext.BEANTRAVERSE_detectRecursions to be enabled.
- Fixed bug in JSON/UON/URL-Encoding serializers where indentation was not correct of first line when BeanTraverseContext.BEANTRAVERSE_initialDepth used.
- Fixed bug in JSON/UON/URL-Encoding serializers where properties past the max depth were being serialized as null instead of being treated as null and not being serialized at all.
- Fixed bug in HTML serializer where tables of maps were not sorted if SERIALIZER_sortMaps was specified.
- SERIALIZER_trimNullProperties has been replaced with Serializer.SERIALIZER_keepNullProperties SERIALIZER_keepNullProperties.
- Improvements to OpenAPI serializer and parser:
  - Collection format can now be specified on OBJECTs to allow key/value pairs to be delimited with the same support as ARRAYs.
  - New OpenApiCommon.OAPI_format OAPI_formatand OpenApiCommon.OAPI_collectionFormat OAPI_collectionFormatproperties.
- Convenience methods added to {@link oaj.httppart.HttpPartSchema} and related classes to simplify schema definitions:

  import static org.apache.juneau.httppart.HttpPartSchema.*; // Old HttpPartSchema s = schema("object") .property("f01", schema("array").collectionFormat("pipes").items(schema("string"))) .property("f02", schema("array").collectionFormat("pipes").items(schema("string", "byte"))) .property("f03", schema("array").collectionFormat("pipes").items(schema("string", "date-time"))) .build(); // New HttpPartSchema s = tObject() .p("f01", tArray(tString())) .p("f02", tArray(tByte())) .p("f03", tArray(tDateTime())) .build();

- Fixes where the bean method/constructor visibility wasn't being used when finding swap methods and constructors.
- HTML-Schema support is being deprecated due to low-use and difficulty in maintaining. It will be removed in 9.0.
- JuneauLogger class is being deprecated. Improvements in logging in Java 8 make it obsolete.
- Bean filters can now be specified programmatically through a builder API.

  // Create a JSON serializer that only includes specified fields on a specific class. WriterSerializer s = JsonSerializer .create() .beanFilters(BeanFilter. create(MyBean. class).bpi("foo,bar,baz").build()) .build();

- BeanContext.REST_pojoSwaps replaced with BeanContext.BEAN_swaps(and builder methods as well).
- New Bean Property Interceptor API for intercepting calls to bean getters/setters.
  - BeanInterceptor
  - {@link oaj.annotation.Bean#interceptor Bean(interceptor)}
  - {@link oaj.BeanContext.Builder#beanInterceptor(Class,Class)}
- Fluent setters that follow the withX convention are now automatically detected by all parsers.

  // A bean with a fluent setter. public class MyBean { public MyBean withFoo(String foo) { this. foo = foo; return this; } }

  Note you could previously use the @BeanProperty annotation to identify these setters.

##### juneau-rest-server

- New RestContext.REST_context REST_context/Rest.context() @Rest(context) setting to allow you to extend the {@link oajr.RestContext} class.
- {@link oajr.annotation.Rest}-annotated classes can now implement the following interfaces directly instead of having to define secondary classes and hook them up through annotations:
  - RestCallHandler- Normally defined through oajr.annotation.Rest.callHandler() @Rest.callHandler().
  - RestInfoProvider - Normally defined through oajr.annotation.Rest.infoProvider() @Rest.infoProvider().
  - RestCallLogger- Normally defined through oajr.annotation.Rest.callLogger() @Rest.callLogger().
  - ClasspathResourceFinder - Normally defined through oajr.annotation.Rest.classpathResourceFinder() @Rest.classpathResourceFinder().
  The methods added for RestInfoProvider are:
  - RestServlet
    - getSwagger(RestRequest)
    - getSiteName(RestRequest)
    - getTitle(RestRequest)
    - getDescription(RestRequest)
    - getMethodSummary(Method,RestRequest)
    - getMethodDescription(Method,RestRequest)
  - BasicRest
    - getSwagger(RestRequest)
    - getSiteName(RestRequest)
    - getTitle(RestRequest)
    - getDescription(RestRequest)
    - getMethodSummary(Method,RestRequest)
    - getMethodDescription(Method,RestRequest)
  The methods added for RestCallLoggerare:
  - RestServlet
    - RestServlet.log(RestCallLoggerConfig,HttpServletRequest,HttpServletResponse) log(RestCallLoggerConfig,HttpServletRequest,HttpServletResponse)
  - BasicRest
    - BasicRest.log(RestCallLoggerConfig,HttpServletRequest,HttpServletResponse) log(RestCallLoggerConfig,HttpServletRequest,HttpServletResponse)
  The methods added for ClasspathResourceFinderare:
  - RestServlet
    - RestServlet.findResource(Class,String,Locale) findResource(Class,String,Locale)
  - BasicRest
    - BasicRest.findResource(Class,String,Locale) findResource(Class,String,Locale)
  The methods added for RestResourceResolverare:
  - RestServlet
    - oajr.RestServlet.resolve(Object,Class,RestContext.Builder,Object...) resolve(Object,Class<T>,RestContext.Builder,Object...)
  - BasicRest
    - oajr.BasicRest.resolve(Object,Class,RestContext.Builder,Object...) resolve(Object,Class<T>,RestContext.Builder,Object...)
- Added the following convenience hook methods on the RestServlet and BasicRestclasses:
  - RestServlet
    - oajr.RestServlet.onInit(RestContext.Builder) onInit(RestContext.Builder)
    - RestServlet.onPostInit(RestContext) onPostInit(RestContext)
    - RestServlet.onPostInitChildFirst(RestContext) onPostInitChildFirst(RestContext)
    - RestServlet.onDestroy(RestContext) onDestroy(RestContext)
    - RestServlet.onStartCall(HttpServletRequest,HttpServletResponse) onStartCall(HttpServletRequest,HttpServletResponse)
    - RestServlet.onPreCall(RestRequest,RestResponse) onPreCall(RestRequest,RestResponse)
    - RestServlet.onPostCall(RestRequest,RestResponse) onPostCall(RestRequest,RestResponse)
    - RestServlet.onEndCall(HttpServletRequest,HttpServletResponse) onEndCall(HttpServletRequest,HttpServletResponse)
  - BasicRest
    - oajr.BasicRest.onInit(RestContext.Builder) onInit(RestContext.Builder)
    - BasicRest.onPostInit(RestContext) onPostInit(RestContext)
    - BasicRest.onPostInitChildFirst(RestContext) onPostInitChildFirst(RestContext)
    - BasicRest.onDestroy(RestContext) onDestroy(RestContext)
    - BasicRest.onStartCall(HttpServletRequest,HttpServletResponse) onStartCall(HttpServletRequest,HttpServletResponse)
    - BasicRest.onPreCall(RestRequest,RestResponse) onPreCall(RestRequest,RestResponse)
    - BasicRest.onPostCall(RestRequest,RestResponse) onPostCall(RestRequest,RestResponse)
    - BasicRest.onEndCall(HttpServletRequest,HttpServletResponse) onEndCall(HttpServletRequest,HttpServletResponse)
- New {@link oajr.annotation.Rest#debugOn() @Rest(debugOn)} annotation for turning on debug mode using class/method identifiers:

  ##### Example:

  // Turn on debug per-request on the class and always on the doX() method. @Rest( debugOn="MyResource=per-request,Mysource.doX=true" // Typically defined via system or env property. ) public class MyResource { @RestMethod public void String doX() { ... }

- BasicRestConfig has been broken up into BasicRestConfig and BasicRestMethods so that you're not forced to implement methods such as getOptions() and getStats() if you're implementing the interface to configure your REST class.
- Any of the following classes can now be instantiated with public static create() methods:
  - RestCallHandler
  - RestCallLogger
  - RestInfoProvider
  - ClasspathResourceFinder
  - RestResourceResolver
  - RestGuard
  - ResponseHandler
- New Path.required() @Path(required)annotation support.
  A path can be marked as not-required when the path variable is resolved by a parent resource like so:

  @Rest(path="/parent/{p1}",children=Child. class) public class Parent { ... } @Rest(path="/child") public class Child { @RestMethod(path="/") public String doGet(@Path(name="p1",required=false) String p1) { // p1 will be null when accessed via "/child" // p1 will be non-null when accessed via "/parent/p1/child". } ... }

  This allows the child resource to be mapped to multiple parents that may resolve various different path variables.
- New RestMethod.paths() @RestMethod(paths) annotation that allows you to map multiple paths to the same Java method.
  Example:

  @RestMethod( name=GET, paths={"/","/{foo}"} ) public String doGet(@Path(name="foo",required=false) String foo) {...}

- The RestMethod @RestMethodannotation is now implied on all unannotated methods of a {@link oajr.annotation.Rest @Rest}-annotated interface.

  @Rest public interface MyRest { String getFoo(); // @RestMethod(name=GET,path="/foo") is implied. }

- Improved RestContext.REST_messages REST_messages support (mostly bug fixes).

##### juneau-rest-server-springboot

- JuneauRestInitializernow provides a no-arg constructor so that it can be used in the @ConfigurationContext(initializers=JuneauRestInitializer. class) when unit testing using @SpringBootTest.
- New ResourceDescription.ResourceDescription(String,String,String)constructor and ResourceDescriptions.append(String,String,String) method.
- New Hyperlinkclass.

##### juneau-rest-client

- Completely revamped RestClient API.
  - All APIs now extend from HttpClient interfaces.
  - Better integration with HttpClient.
  - New fluent-style methods with many new convenience methods.
  - Updated juneau-rest-client.
- @RemoteMethod-annotated methods can now return {@link java.util.concurrent.Future Futures} and {@link java.util.concurrent.CompletableFuture CompletableFutures} for concurrent processing of requests.
  Example:

  @Remote public interface MyInterface { public Future<String> doGet(); } MyInterface i = client.getRemote(MyInterface. class, "http://localhost:12345/myInterface"); Future<String> f = i.doGet(); // Do other stuff. String result = f.get();

- Additions to {@link oaj.http.remote.Remote} annotation:
  - {@link oaj.http.remote.Remote#version version} - Adds a client version header to all requests.
  - {@link oaj.http.remote.Remote#headers headers} - Adds a set of headers to all requests.
  - headerSupplier - Adds a dynamic supplier of headers to all requests.

##### juneau-rest-mock

- The MockRest and MockRemote classes have been remove entirely and all existing functions have been moved into the improved MockRestClient class. All REST test mocking can be done through this single class.