5.2.0.0 (Dec 30, 2015)

Juno 5.2.0.0 is a major update. Major changes have been made to the microservice architecture and config INI file APIs.

##### Core

- Significant changes and enhancements to the `org.apache.juneau.config` API.
  - More consistent handling of comma-delimited lists of objects.
  - New methods in `ConfigFile`:
    - `ConfigFile.getStringArray(String)`,`ConfigFile.getStringArray(String,String[])`
    - `ConfigFile.getSectionAsBean(String,Class)` - Instantiate a new bean with property values in the specified section..
    - `ConfigFile.writeProperties(String,Object,boolean,Class[])` - Copy the properties in a config file section into properties on an existing bean or POJO.
    - `ConfigFile.getSectionMap(String)` - Get all the resolved values in a section.
    - `ConfigFile.containsNonEmptyValue(String)`
    - `ConfigFile.isEncoded(String)`
    - `ConfigFile.addListener(ConfigFileListener)` - Listen for modification events on the config file.
    - `ConfigFile.merge(ConfigFile)` - Merge the contents of another config file into this config file.
    - `ConfigFile.getResolving()`, `ConfigFile.getResolving(StringVarResolver)` - Return an instance of the config file that resolves string variables. Much more efficient than the previous design since the same underlying config file object is shared.
    - `ConfigFile.toWritable()` - Wraps the config file in a {@link oaj.Writable} interface so that it can be serialized by the REST interface as a plain-text INI file instead of as a serialized POJO.
    - `ConfigFile.getInt(String)` - Now supports "M" and "K" to identify millions and thousands.
  - New methods in `ConfigMgr`:
    - `ConfigMgr.create()`, `ConfigMgr.create(Reader)`, `ConfigMgr.create(File)`
    - `ConfigMgr.deleteAll()`
  - New methods in `Section`:
    - `Section.setParent(ConfigFileImpl)` - Used by parsers to set the config file for this section.
    - `Section.setName(String)` - Used by parsers to set the name for this section.
  - New interfaces:
    - `org.apache.juneau.config.ConfigFileListener`
    - `org.apache.juneau.config.SectionListener`
    - `org.apache.juneau.config.EntryListener`
  - `org.apache.juneau.config.Encoder` methods have access to field names to use them as salt values.
  - The name of the default section is now "default". Before it was just null.
  - `org.apache.juneau.config.XorEncoder` XOR key can be overridden through the "org.apache.juneau.config.XorEncoder.key" system property.
- Support for converting Strings to POJOs if the POJO class has any of the following static methods:
  - `fromString(String)`
  - `valueOf(String)` (e.g. enums)
  - `parse(String)` (e.g. logging `Level` class)
  - `parseString(String)`
  - `forName(String)` (e.g. `Class` and `Charset` classes)
- Support for parsing into objects with unbound type variables. For example, if you have a class `Pair<S,T>` and you try to parse into this class (e.g. `parser.parse(in, Pair.class)`), the unbound type variables is interpreted as `Object` instead of throwing an exception.
- Support for serializing/parsing the following new types:
  - `AtomicInteger`
  - `AtomicLong`
  - `BigInteger`
  - `BigDecimal`
- Parsers have been enhanced to allow parent POJOs and field names to be passed into child POJOs. New {@link oaj.annotation.NameProperty @NameProperty} and {@link oaj.annotation.ParentProperty @ParentProperty} annotations are provided for identifying methods for setting names and parent POJOs on child POJOs. For example, the config file `Section` class represents a section in a config file. It needs to know it's own name and have a link to the `ConfigFile` that it belongs to. With these new annotations, config files can be reconstructed using any of the parsers.
- New classes and interfaces:
  - {@link oaj.Streamable} interface for identifying objects that can be serialized directly to an output stream.
  - {@link oaj.Writable} interface for identifying objects that can be serialized directly to a writer.
  - `StringObject` class that can be used for delayed object serialization.
  - {@link oaj.internal.ByteArrayCache}
  - {@link oaj.internal.ByteArrayInOutStream}
  - {@link oaj.internal.FileUtils}
  - {@link oaj.internal.ThrowableUtils}
  - `StringVarMultipart`
  - `StringVarWithDefault`
- New fields on {@link oaj.ObjectList}:
  - {@link oaj.ObjectList#EMPTY_LIST}
- New fields and methods on {@link oaj.ObjectMap}:
  - {@link oaj.ObjectMap#EMPTY_MAP}
  - {@link oaj.ObjectMap#getStringArray(String)}
  - {@link oaj.ObjectMap#getStringArray(String,String[])}
  - {@link oaj.ObjectMap#putIfNull(String,Object)}
  - {@link oaj.ObjectMap#putIfEmpty(String,Object)}
- New methods in {@link oaj.internal.ArrayUtils}:
  - {@link oaj.internal.ArrayUtils#contains(Object,Object[])}
  - {@link oaj.internal.ArrayUtils#indexOf(Object,Object[])}
  - {@link oaj.internal.ArrayUtils#toPrimitiveArray(Object)}
- New methods in {@link oaj.internal.IOUtils}:
  - `IOUtils.pipe(Reader,Writer)`
  - {@link oaj.internal.IOUtils#read(File)}
  - {@link oaj.internal.IOUtils#readFile(String)}
  - {@link oaj.internal.IOUtils#write(File,Reader)}
- New methods on {@link oaj.utils.PojoRest}:
  - `PojoRest.get(Class,String,Object)`
  - {@link oaj.utils.PojoRest#getString(String)}
  - {@link oaj.utils.PojoRest#getString(String,String)}
  - {@link oaj.utils.PojoRest#getInt(String)}
  - {@link oaj.utils.PojoRest#getInt(String,Integer)}
  - {@link oaj.utils.PojoRest#getLong(String)}
  - {@link oaj.utils.PojoRest#getLong(String,Long)}
  - {@link oaj.utils.PojoRest#getBoolean(String)}
  - {@link oaj.utils.PojoRest#getBoolean(String,Boolean)}
  - {@link oaj.utils.PojoRest#getMap(String)}
  - {@link oaj.utils.PojoRest#getMap(String,Map)}
  - {@link oaj.utils.PojoRest#getList(String)}
  - {@link oaj.utils.PojoRest#getList(String,List)}
  - {@link oaj.utils.PojoRest#getObjectMap(String)}
  - {@link oaj.utils.PojoRest#getObjectMap(String,ObjectMap)}
  - {@link oaj.utils.PojoRest#getObjectList(String)}
  - {@link oaj.utils.PojoRest#getObjectList(String,ObjectList)}
- New methods on {@link oaj.utils.ProcBuilder}:
  - {@link oaj.utils.ProcBuilder#pipeTo(Writer,boolean)}
  - {@link oaj.utils.ProcBuilder#pipeTo(Writer)}
  - {@link oaj.utils.ProcBuilder#logTo(Writer,boolean)}
  - {@link oaj.utils.ProcBuilder#logTo(Writer)}
  - {@link oaj.utils.ProcBuilder#logTo(Level,Logger)}
  - {@link oaj.utils.ProcBuilder#maxExitStatus(int)}
- New methods on {@link oaj.internal.StringUtils}:
  - {@link oaj.internal.StringUtils#isEmpty(Object)}
  - {@link oaj.internal.StringUtils#nullIfEmpty(String)}
  - {@link oaj.internal.StringUtils#base64EncodeToString(String)}
  - {@link oaj.internal.StringUtils#base64Encode(byte[])}
  - {@link oaj.internal.StringUtils#base64DecodeToString(String)}
  - {@link oaj.internal.StringUtils#base64Decode(String)}
  - {@link oaj.internal.StringUtils#generateUUID(int)}
  - {@link oaj.internal.StringUtils#trim(String)}
  - `StringUtils.parseISO8601Date(String)`
  - {@link oaj.internal.StringUtils#replaceVars(String,Map)}
  - {@link oaj.internal.StringUtils#pathStartsWith(String,String)}
  - {@link oaj.internal.StringUtils#pathStartsWith(String,String[])}
- New `StringVar.doResolve(String)` method.
- New `StringVarResolver.DEFAULT` field.
- Eliminated dependency on `javax.mail.internet.MimeUtility` by implementing our own {@link oaj.internal.StringUtils#base64Encode(byte[])} method.
- {@link oaj.transforms.CalendarSwap} and {@link oaj.transforms.DateSwap} classes now handle blank input better. Returns null instead of throwing an exception.
- {@link oaj.html.HtmlDocSerializer} specifies the default CSS location as `/servletPath/style.css` instead of `/servletPath/htdocs/juneau.css`. This coincides with enhancements made in the server code for specifying styles.
- {@link oaj.html.HtmlDocSerializer} wraps output in two div tags instead of one (e.g. `<div class='outerdata'><div class='data' id='data'>...</div></div>`). Needed for supporting the new devops look-and-feel.
- Fixed indentation inconsistencies in {@link oaj.html.HtmlDocSerializer}.
- Renamed HtmlSchemaSerializer to HtmlSchemaDocSerializer.
- RDF serializers and parsers now support `RdfProperties.RDF_looseCollection` loose collections.
- RDF parser handles case where resources point to themselves (an unfortunate behavior in JFS RDF documents).
- JSON parser with throw an exception in strict mode if it encounters numbers that are valid in Java but invalid in JSON (e.g. octal, hexadecimal numbers).
- {@link oaj.parser.Parser} methods now check for null input.
- {@link oaj.serializer.SerializerGroup} and {@link oaj.parser.ParserGroup} ignores serializers and parsers if they throw `NoClassDefFoundErrors`.
- {@link oaj.urlencoding.UrlEncodingParser} creates lists if the same attribute name is encountered more than once. Before it would just replace the previous value with the new value.
- New `UrlEncodingSerializer.DEFAULT_SIMPLE_EXPANDED` serializer.
- Changes to {@link oaj.utils.Args}:
  - `getMainArg(int)` changed to {@link oaj.utils.Args#getArg(int)}. Non-existent arguments are returned as null instead of blank strings. This is more inline with the behavior of the rest of the library.
  - New {@link oaj.utils.Args#hasArg(int)} method.
- Removed `org.apache.juneau.utils.CharsetUtils` class.
- Removed `org.apache.juneau.utils.ConcurrentIdentityList` class.
- Fixed bug in {@link oaj.internal.MultiIterable} class.
- {@link oaj.utils.PojoIntrospector} must now be instantiated with a `ReaderParser`. Simplifies the API on the class.
- {@link oaj.utils.PojoRest} must now be instantiated with a `ReaderParser`. Simplifies the API on the class.
- {@link oaj.utils.MessageBundle} and `SafeResourceMultiBundle` moved from server component.
- Several bug fixes and performance improvements in `StringVarResolver`.
- Various enhancements to {@link oaj.internal.TeeWriter} and {@link oaj.internal.TeeOutputStream}.
- Renamed CharSet to {@link oaj.internal.AsciiSet}.
- {@link oaj.serializer.SerializerGroup} and {@link oaj.parser.ParserGroup} now ignores `NoClassDefFoundErrors` so that resources that include Jena support can continue to operate even if the Jena libraries are not present.
- New {@link oaj.internal.FileUtils#createTempFile(String)} method.
- New {@link oaj.utils.PojoQuery} modified to handle bean getters that throw exceptions.

##### Client

- Upgraded to use Apache HttpClient 4.5.
- New classes:
  - {@link oajrc.AllowAllRedirects}
  - {@link oajrc.HttpMethod}
  - {@link oajrc.ResponsePattern}
  - {@link oajrc.SimpleX509TrustManager}
  - `SSLOpts`
- Removed `org.apache.juneau.rest.client.LaxRedirectStrategy`. Use HTTP Client equivalent.
- New methods on {@link oajrc.RestCall}:
  - `RestCall#addInterceptor(RestCallInterceptor)`
  - {@link oajrc.RestCall#pipeTo(Writer)}
  - {@link oajrc.RestCall#pipeTo(Writer,boolean)}
  - {@link oajrc.RestCall#pipeTo(String,Writer,boolean)}
  - {@link oajrc.RestCall#getWriter(String)}
  - {@link oajrc.RestCall#pipeTo(OutputStream)}
  - {@link oajrc.RestCall#pipeTo(OutputStream,boolean)}
  - {@link oajrc.RestCall#pipeTo(String,OutputStream,boolean)}
  - {@link oajrc.RestCall#getOutputStream(String)}
  - {@link oajrc.RestCall#byLines()}
  - {@link oajrc.RestCall#captureResponse()}
  - {@link oajrc.RestCall#successPattern(String)}
  - {@link oajrc.RestCall#failurePattern(String)}
  - `RestCall#addResponsePattern(ResponsePattern)`
  - {@link oajrc.RestCall#run()} - Renamed from `execute()`.
  - {@link oajrc.RestCall#getCapturedResponse()}
  - {@link oajrc.RestCall#getResponsePojoRest(Class)}
  - {@link oajrc.RestCall#getResponsePojoRest()}
  - {@link oajrc.RestCall#logTo(Level,Logger)}
  - {@link oajrc.RestCall#setConfig(RequestConfig)}
- New lifecycle listener methods on {@link oajrc.RestCallInterceptor}:
  - {@link oajrc.RestCallInterceptor#onInit(RestCall)}
  - {@link oajrc.RestCallInterceptor#onClose(RestCall)}
- New methods on {@link oajrc.RestClient}:
  - `RestClient.setBasicAuth(String,int,String,String)`
  - `RestClient.logTo(Level,Logger)`
  - `RestClient.setRootUrl(String)`
  - `RestClient.enableSSL(SSLOpts)`
  - `RestClient.enableLaxSSL()`
  - {@link oajrc.RestClient#doCall(HttpMethod,Object,Object)}
  - `RestClient.createHttpClientBuilder()`
- New passthrough methods on {@link oajrc.RestClient} defined on `HttpClientBuilder`:
  - `RestClient.setRedirectStrategy(RedirectStrategy)`
  - `RestClient.setDefaultCookieSpecRegistry(Lookup)`
  - `RestClient.setRequestExecutor(HttpRequestExecutor)`
  - `RestClient.setSSLHostnameVerifier(HostnameVerifier)`
  - `RestClient.setPublicSuffixMatcher(PublicSuffixMatcher)`
  - `RestClient.setSSLContext(SSLContext)`
  - `RestClient.setSSLSocketFactory(LayeredConnectionSocketFactory)`
  - `RestClient.setMaxConnTotal(int)`
  - `RestClient.setMaxConnPerRoute(int)`
  - `RestClient.setDefaultSocketConfig(SocketConfig)`
  - `RestClient.setDefaultConnectionConfig(ConnectionConfig)`
  - `RestClient.setConnectionTimeToLive(long,TimeUnit)`
  - `RestClient.setConnectionManager(HttpClientConnectionManager)`
  - `RestClient.setConnectionManagerShared(boolean)`
  - `RestClient.setConnectionReuseStrategy(ConnectionReuseStrategy)`
  - `RestClient.setKeepAliveStrategy(ConnectionKeepAliveStrategy)`
  - `RestClient.setTargetAuthenticationStrategy(AuthenticationStrategy)`
  - `RestClient.setProxyAuthenticationStrategy(AuthenticationStrategy)`
  - `RestClient.setUserTokenHandler(UserTokenHandler)`
  - `RestClient.disableConnectionState()`
  - `RestClient.setSchemePortResolver(SchemePortResolver)`
  - `RestClient.setUserAgent(String userAgent)`
  - `RestClient.setDefaultHeaders(Collection)`
  - `RestClient.addInterceptorFirst(HttpResponseInterceptor)`
  - `RestClient.addInterceptorLast(HttpResponseInterceptor)`
  - `RestClient.addInterceptorFirst(HttpRequestInterceptor)`
  - `RestClient.addInterceptorLast(HttpRequestInterceptor)`
  - `RestClient.disableCookieManagement()`
  - `RestClient.disableContentCompression()`
  - `RestClient.disableAuthCaching()`
  - `RestClient.setHttpProcessor(HttpProcessor)`
  - `RestClient.setRetryHandler(HttpRequestRetryHandler)`
  - `RestClient.disableAutomaticRetries()`
  - `RestClient.setProxy(HttpHost)`
  - `RestClient.setRoutePlanner(HttpRoutePlanner)`
  - `RestClient.disableRedirectHandling()`
  - `RestClient.setConnectionBackoffStrategy(ConnectionBackoffStrategy)`
  - `RestClient.setBackoffManager(BackoffManager)`
  - `RestClient.setServiceUnavailableRetryStrategy(ServiceUnavailableRetryStrategy)`
  - `RestClient.setDefaultCookieStore(CookieStore)`
  - `RestClient.setDefaultCredentialsProvider(CredentialsProvider)`
  - `RestClient.setDefaultAuthSchemeRegistry(Lookup)`
  - `RestClient.setContentDecoderRegistry(Map)`
  - `RestClient.setDefaultRequestConfig(RequestConfig)`
  - `RestClient.useSystemProperties()`
  - `RestClient.evictExpiredConnections()`
  - `RestClient.evictIdleConnections(long,TimeUnit)`
- `JazzRestClient` now supports OIDC authentication.
- These classes are now deprecated and will be removed in a future release:
  - `org.apache.juneau.rest.client.jazz.CertificateStore`
  - `org.apache.juneau.rest.client.jazz.ICertificateValidator`
  - `org.apache.juneau.rest.client.jazz.ITrustStoreProvider`
  - `org.apache.juneau.rest.client.jazz.LenientCertificateValidator`
  - `org.apache.juneau.rest.client.jazz.SharedTrustStoreProvider`
  - `org.apache.juneau.rest.client.jazz.ValidatingX509TrustManager`

##### Server

- New `ReaderResource` class. Represents the contents of a text file with convenience methods for resolving `StringVar` variables and adding HTTP response headers. REST Java methods can return instances of these to serialize `Readers` containing text with `StringVarResolver` variables in them.
- New `StreamResource` class. REST Java methods can return instances of these to serialize `OutputStreams`.
- Fixed a bug in the stack trace hash algorithm in {@link oajr.RestException}.
- New methods in {@link oajr.RestRequest}:
  - `RestRequest.getReaderResource(String)` - Replaces `getVarResource(String)`.
  - `RestRequest.getReaderResource(String,boolean)`
  - `RestRequest.getReaderResource(String,boolean,String)`
- Changes in {@link oajr.RestResponse}:
  - Don't set `Content-Encoding: identity` when no encoding is used. Some clients don't interpret it correctly.
- New methods in {@link oajr.RestServlet}:
  - `RestServlet.getChildClasses()` - Programmatic equivalent to {@link oajr.annotation.RestResource#children() @RestResource(children)} annotation.
  - `RestServlet.shouldLog(HttpServletRequest,HttpServletResponse,RestException)`
  - `RestServlet.shouldLogStackTrace(HttpServletRequest,HttpServletResponse,RestException)`
  - `RestServlet.logObjects(Level,String,Object[])`
  - `RestServlet.resolveStaticFile(String)`
  - `RestServlet.createStyleSheet()`
  - `RestServlet.createFavIcon()`
  - `RestServlet.createStaticFilesMap()`
  - `RestServlet.getConfigMgr()`
- Removed {@link oaj.jso.JsoParser} from {@link oajr.BasicRestServlet} and `RestServletJenaDefault`. These may represent a security risk if not handled correctly, so removed them as a precaution.
- Removed `RestServletProperties.REST_htDocsFolder`. Replaced with {@link oajr.annotation.RestResource#staticFiles() @RestResource(staticFiles)}.
- New annotations on {@link oajr.annotation.RestResource @RestResource}.
  - `RestResource.stylesheet()`
  - `RestResource.favicon()`
  - {@link oajr.annotation.RestResource#staticFiles() @RestResource(staticFiles)}
- Eliminated `org.apache.juneau.rest.jaxrs.JsonProvider` class. Some JAX-RS implementations use code scanning to find providers, so if you were using `DefaultJenaProvider`, it would pick up `JsonProvider` as well. It's easy enough to create your own implementation if needed.
- OPTIONS pages now specify `consumes` and `produces` fields instead of `accept` and `contentType` which was confusing.
- Eliminated `properties` from OPTIONS pages.
- New `ResourceLink.ResourceLink(String,RestRequest,String,Object[])` constructor.
- New response handlers:
  - `StreamableHandler` - Allows REST Java methods to return instances of {@link oaj.Streamable}.
  - `WritableHandler` - Allows REST Java methods to return instances of {@link oaj.Writable}.
- New DevOps stylesheet.
- Servlet initialization and HTTP requests are now logged at FINE level.
- Added abstract modifier on various RestServlet subclasses to indicate that they're meant to be subclassed.
- New `RestUtils.trimPathInfo(StringBuffer,String,String)` method.

##### Microservice

- Completely revamped API.
- New {@link oaj.microservice.Microservice} class that serves as a generic interface for microservices and their lifecycles.
- New {@link oaj.microservice.RestMicroservice} class that implements a microservice consisting of a REST interface.
  - REST resources and configuration settings can be defined through either manifest files or config files.
  - Enhanced logging support.
  - Easy-to-configure SSL support.
  - BASIC auth support.
  - Automatic restartability if the config file changes.
- Eliminated `org.apache.juneau.microservice.Main` class. This is replaced by the microservice classes defined above.
- `Resource` and `ResourceGroup` classes now support the following new string variables:
  - "$A{key,default}"" - Command line arguments.
  - "$MF{key,default}"" - Manifest file entries.
- CSS stylesheet now configurable through config file entry "REST/stylesheet".
- New {@link oaj.microservice.BasicRestServletJena} class if you want your REST interface to support RDF.
- Eliminated the following classes:
  - `org.apache.juneau.microservice.RootResource`
  - `org.apache.juneau.microservice.SampleResource`
- New predefined reusable resources:
  - {@link oaj.microservice.resources.ConfigResource} - REST resource for viewing and editing microservice config file.
  - {@link oaj.microservice.resources.LogsResource} - REST resource for viewing log files.
  - {@link oaj.microservice.resources.SampleRootResource} - Sample REST resource that contains the config and logs resource as children.
  - {@link oaj.microservice.resources.ShutdownResource} - REST resource for stopping the microservice JVM. Useful for testing purposes.

##### Samples

- Converted to a REST microservice.
- Look-and-feel changed to IBM DevOps.

##### Documentation Updates

- org.apache.juneau.microservice - New package-level javadoc.
- org.apache.juneau.config - New package-level javadoc.
- `StringVarResolver` - New documentation.
- org.apache.juneau.rest.client - New package-level javadoc.
- `Overview / Samples` - New section.
- org.apache.juneau.transform / Stop Classes - New section.
- org.apache.juneau.rest - Extensive updates.