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 {@del ConfigFile}:
- {@del ConfigFile#getStringArray(String)},{@del ConfigFile#getStringArray(String,String[])}
- {@del ConfigFile#getSectionAsBean(String,Class)} - Instantiate a new bean with property values in the specified section..
- {@del ConfigFile#writeProperties(String,Object,boolean,Class[])} - Copy the properties in a config file section into properties on an existing bean or POJO.
- {@del ConfigFile#getSectionMap(String)} - Get all the resolved values in a section.
- {@del ConfigFile#containsNonEmptyValue(String)}
- {@del ConfigFile#isEncoded(String)}
- {@del ConfigFile#addListener(ConfigFileListener)} - Listen for modification events on the config file.
- {@del ConfigFile#merge(ConfigFile)} - Merge the contents of another config file into this config file.
- {@del ConfigFile#getResolving()}, {@del 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.
- {@del ConfigFile#toWritable()} - Wraps the config file in a {@del 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.
- {@del ConfigFile#getInt(String)} - Now supports "M" and "K" to identify millions and thousands.
- New methods in {@del ConfigMgr}:
- {@del ConfigMgr#create()}, {@del ConfigMgr#create(Reader)}, {@del ConfigMgr#create(File)}
- {@del ConfigMgr#deleteAll()}
- New methods in {@del Section}:
- {@del Section#setParent(ConfigFileImpl)} - Used by parsers to set the config file for this section.
- {@del Section#setName(String)} - Used by parsers to set the name for this section.
- New interfaces:
- {@del org.apache.juneau.config.ConfigFileListener}
- {@del org.apache.juneau.config.SectionListener}
- {@del org.apache.juneau.config.EntryListener}
- {@del 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.
- {@del 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 {@del Section} class represents a section
in a config file. It needs to know it's own name and have a link to the {@del ConfigFile}
that it belongs to. With these new annotations, config files can be reconstructed using any of the parsers.
- New classes and interfaces:
- {@del oaj.Streamable} interface for identifying objects that can be serialized directly to an output stream.
- {@del oaj.Writable} interface for identifying objects that can be serialized directly to a writer.
- {@del StringObject} class that can be used for delayed object serialization.
- {@del ByteArrayCache}
- {@del oaj.internal.ByteArrayInOutStream}
- {@link oaj.internal.FileUtils}
- {@link oaj.internal.ThrowableUtils}
- {@del StringVarMultipart}
- {@del StringVarWithDefault}
- New fields on {@del oaj.ObjectList}:
- {@del oaj.ObjectList#EMPTY_LIST}
- New fields and methods on {@del oaj.ObjectMap}:
- {@del oaj.ObjectMap#EMPTY_MAP}
- {@del oaj.ObjectMap#getStringArray(String)}
- {@del oaj.ObjectMap#getStringArray(String,String[])}
- {@del oaj.ObjectMap#putIfNull(String,Object)}
- {@del oaj.ObjectMap#putIfEmpty(String,Object)}
- New methods in {@link oaj.internal.ArrayUtils}:
- {@del oaj.internal.ArrayUtils#contains(Object,Object[])}
- {@del oaj.internal.ArrayUtils#indexOf(Object,Object[])}
- {@del oaj.internal.ArrayUtils#toPrimitiveArray(Object)}
- New methods in {@link oaj.internal.IOUtils}:
- {@del IOUtils#pipe(Reader,Writer)}
- {@link oaj.internal.IOUtils#read(File)}
- {@del IOUtils#readFile(String)}
- {@del IOUtils#write(File,Reader)}
- New methods on {@del oaj.utils.PojoRest}:
- {@del PojoRest#get(Class,String,Object)}
- {@del oaj.utils.PojoRest#getString(String)}
- {@del oaj.utils.PojoRest#getString(String,String)}
- {@del oaj.utils.PojoRest#getInt(String)}
- {@del oaj.utils.PojoRest#getInt(String,Integer)}
- {@del oaj.utils.PojoRest#getLong(String)}
- {@del oaj.utils.PojoRest#getLong(String,Long)}
- {@del oaj.utils.PojoRest#getBoolean(String)}
- {@del oaj.utils.PojoRest#getBoolean(String,Boolean)}
- {@del oaj.utils.PojoRest#getMap(String)}
- {@del oaj.utils.PojoRest#getMap(String,Map)}
- {@del oaj.utils.PojoRest#getList(String)}
- {@del oaj.utils.PojoRest#getList(String,List)}
- {@del getObjectMap(String)}
- {@del getObjectMap(String,ObjectMap)}
- {@del getObjectList(String)}
- {@del getObjectList(String,ObjectList)}
- New methods on {@del oaj.utils.ProcBuilder}:
- {@del oaj.utils.ProcBuilder#pipeTo(Writer,boolean)}
- {@del oaj.utils.ProcBuilder#pipeTo(Writer)}
- {@del oaj.utils.ProcBuilder#logTo(Writer,boolean)}
- {@del oaj.utils.ProcBuilder#logTo(Writer)}
- {@del oaj.utils.ProcBuilder#logTo(Level,Logger)}
- {@del oaj.utils.ProcBuilder#maxExitStatus(int)}
- New methods on {@link oaj.internal.StringUtils}:
- {@del 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)}
- {@del oaj.internal.StringUtils#generateUUID(int)}
- {@link oaj.internal.StringUtils#trim(String)}
- {@del StringUtils#parseISO8601Date(String)}
- {@link oaj.internal.StringUtils#replaceVars(String,Map)}
- {@del oaj.internal.StringUtils#pathStartsWith(String,String)}
- {@del oaj.internal.StringUtils#pathStartsWith(String,String[])}
- New {@del StringVar#doResolve(String)} method.
- New {@del StringVarResolver#DEFAULT} field.
- Eliminated dependency on javax.mail.internet.MimeUtility by implementing our own {@link oaj.internal.StringUtils#base64Encode(byte[])} method.
- {@del oaj.transforms.CalendarSwap} and {@del 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 {@del HtmlSchemaSerializer} to {@del 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.
- {@del oaj.serializer.SerializerGroup} and {@del 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 {@del UrlEncodingSerializer#DEFAULT_SIMPLE_EXPANDED} serializer.
- Changes to {@del Args}:
- getMainArg(int) changed to {@del 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 {@del 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.
- {@del oaj.utils.PojoIntrospector} must now be instantiated with a ReaderParser.
Simplifies the API on the class.
- {@del oaj.utils.PojoRest} must now be instantiated with a ReaderParser.
Simplifies the API on the class.
- {@del oaj.utils.MessageBundle} and SafeResourceMultiBundle moved from server component.
- Several bug fixes and performance improvements in {@del StringVarResolver}.
- Various enhancements to {@del oaj.internal.TeeWriter} and {@del oaj.internal.TeeOutputStream}.
- Renamed {@del CharSet} to {@link oaj.internal.AsciiSet}.
- {@del oaj.serializer.SerializerGroup} and {@del 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:
- {@del oajrc.AllowAllRedirects}
- {@del oajrc.HttpMethod}
- {@del oajrc.ResponsePattern}
- {@del oajrc.SimpleX509TrustManager}
- {@del SSLOpts}
- Removed org.apache.juneau.rest.client.LaxRedirectStrategy. Use HTTP Client equivalent.
- New methods on {@del oajrc.RestCall}:
- {@del RestCall#addInterceptor(RestCallInterceptor)}
- {@del oajrc.RestCall#pipeTo(Writer)}
- {@del oajrc.RestCall#pipeTo(Writer,boolean)}
- {@del oajrc.RestCall#pipeTo(String,Writer,boolean)}
- {@del oajrc.RestCall#getWriter(String)}
- {@del oajrc.RestCall#pipeTo(OutputStream)}
- {@del oajrc.RestCall#pipeTo(OutputStream,boolean)}
- {@del oajrc.RestCall#pipeTo(String,OutputStream,boolean)}
- {@del oajrc.RestCall#getOutputStream(String)}
- {@del oajrc.RestCall#byLines()}
- {@del oajrc.RestCall#captureResponse()}
- {@del oajrc.RestCall#successPattern(String)}
- {@del oajrc.RestCall#failurePattern(String)}
- {@del RestCall#addResponsePattern(ResponsePattern)}
- {@del oajrc.RestCall#run()} - Renamed from execute().
- {@del oajrc.RestCall#getCapturedResponse()}
- {@del oajrc.RestCall#getResponsePojoRest(Class)}
- {@del oajrc.RestCall#getResponsePojoRest()}
- {@del oajrc.RestCall#logTo(Level,Logger)}
- {@del oajrc.RestCall#setConfig(RequestConfig)}
- New lifecycle listener methods on {@del oajrc.RestCallInterceptor}:
- {@del RestCallInterceptor#onInit(RestCall)}
- {@del RestCallInterceptor#onClose(RestCall)}
- New methods on {@link oajrc.RestClient}:
- {@del RestClient#setBasicAuth(String,int,String,String)}
- {@del RestClient#logTo(Level,Logger)}
- {@del RestClient#setRootUrl(String)}
- {@del RestClient#enableSSL(SSLOpts)}
- {@del RestClient#enableLaxSSL()}
- {@del RestClient#doCall(HttpMethod,Object,Object)}
- {@del RestClient#createHttpClientBuilder()}
- New passthrough methods on {@link oajrc.RestClient} defined on HttpClientBuilder:
- {@del RestClient#setRedirectStrategy(RedirectStrategy)}
- {@del RestClient#setDefaultCookieSpecRegistry(Lookup)}
- {@del RestClient#setRequestExecutor(HttpRequestExecutor)}
- {@del RestClient#setSSLHostnameVerifier(HostnameVerifier)}
- {@del RestClient#setPublicSuffixMatcher(PublicSuffixMatcher)}
- {@del RestClient#setSSLContext(SSLContext)}
- {@del RestClient#setSSLSocketFactory(LayeredConnectionSocketFactory)}
- {@del RestClient#setMaxConnTotal(int)}
- {@del RestClient#setMaxConnPerRoute(int)}
- {@del RestClient#setDefaultSocketConfig(SocketConfig)}
- {@del RestClient#setDefaultConnectionConfig(ConnectionConfig)}
- {@del RestClient#setConnectionTimeToLive(long,TimeUnit)}
- {@del RestClient#setConnectionManager(HttpClientConnectionManager)}
- {@del RestClient#setConnectionManagerShared(boolean)}
- {@del RestClient#setConnectionReuseStrategy(ConnectionReuseStrategy)}
- {@del RestClient#setKeepAliveStrategy(ConnectionKeepAliveStrategy)}
- {@del RestClient#setTargetAuthenticationStrategy(AuthenticationStrategy)}
- {@del RestClient#setProxyAuthenticationStrategy(AuthenticationStrategy)}
- {@del RestClient#setUserTokenHandler(UserTokenHandler)}
- {@del RestClient#disableConnectionState()}
- {@del RestClient#setSchemePortResolver(SchemePortResolver)}
- {@del RestClient.setUserAgent(String)}
- {@del RestClient#setDefaultHeaders(Collection)}
- {@del RestClient#addInterceptorFirst(HttpResponseInterceptor)}
- {@del RestClient#addInterceptorLast(HttpResponseInterceptor)}
- {@del RestClient#addInterceptorFirst(HttpRequestInterceptor)}
- {@del RestClient#addInterceptorLast(HttpRequestInterceptor)}
- {@del RestClient#disableCookieManagement()}
- {@del RestClient#disableContentCompression()}
- {@del RestClient#disableAuthCaching()}
- {@del RestClient#setHttpProcessor(HttpProcessor)}
- {@del RestClient#setRetryHandler(HttpRequestRetryHandler)}
- {@del RestClient#disableAutomaticRetries()}
- {@del RestClient#setProxy(HttpHost)}
- {@del RestClient#setRoutePlanner(HttpRoutePlanner)}
- {@del RestClient#disableRedirectHandling()}
- {@del RestClient#setConnectionBackoffStrategy(ConnectionBackoffStrategy)}
- {@del RestClient#setBackoffManager(BackoffManager)}
- {@del RestClient#setServiceUnavailableRetryStrategy(ServiceUnavailableRetryStrategy)}
- {@del RestClient#setDefaultCookieStore(CookieStore)}
- {@del RestClient#setDefaultCredentialsProvider(CredentialsProvider)}
- {@del RestClient#setDefaultAuthSchemeRegistry(Lookup)}
- {@del RestClient#setContentDecoderRegistry(Map)}
- {@del RestClient#setDefaultRequestConfig(RequestConfig)}
- {@del RestClient#useSystemProperties()}
- {@del RestClient#evictExpiredConnections()}
- {@del 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 {@del ReaderResource} class.
Represents the contents of a text file with convenience methods for resolving
{@del StringVar} variables and adding HTTP response headers.
REST Java methods can return instances of these to serialize Readers
containing text with {@del StringVarResolver} variables in them.
- New {@del StreamResource} class.
REST Java methods can return instances of these to serialize OutputStreams.
- Fixed a bug in the stack trace hash algorithm in {@del oajr.RestException}.
- New methods in {@link oajr.RestRequest}:
- {@del RestRequest#getReaderResource(String)} - Replaces getVarResource(String).
- {@del RestRequest#getReaderResource(String,boolean)}
- {@del 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 {@del oajr.RestServlet}:
- {@del RestServlet#getChildClasses()} - Programmatic equivalent to {@del @RestResource(children)} annotation.
- {@del RestServlet#shouldLog(HttpServletRequest,HttpServletResponse,RestException)}
- {@del RestServlet#shouldLogStackTrace(HttpServletRequest,HttpServletResponse,RestException)}
- {@del RestServlet#logObjects(Level,String,Object[])}
- {@del RestServlet#resolveStaticFile(String)}
- {@del RestServlet#createStyleSheet()}
- {@del RestServlet#createFavIcon()}
- {@del RestServlet#createStaticFilesMap()}
- {@del RestServlet#getConfigMgr()}
- Removed {@del oaj.jso.JsoParser}
from {@del oajr.BasicRestServlet} and {@del RestServletJenaDefault}.
These may represent a security risk if not handled correctly, so removed
them as a precaution.
- Removed RestServletProperties.REST_htDocsFolder. Replaced with {@del @RestResource(staticFiles)}}.
- New annotations on {@del @RestResource}.
- {@del RestResource#stylesheet()}
- {@del RestResource#favicon()}
- {@del @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 {@del ResourceLink#ResourceLink(String,RestRequest,String,Object[])} constructor.
- New response handlers:
- {@del StreamableHandler} - Allows REST Java methods to return instances of {@del oaj.Streamable}.
- {@del WritableHandler} - Allows REST Java methods to return instances of {@del 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 {@del 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 {@del 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.
- {@del Resource} and {@del 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 {@del 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
- {@del org.apache.juneau.microservice} - New package-level javadoc.
- {@del org.apache.juneau.config} - New package-level javadoc.
- {@del StringVarResolver} - New documentation.
- {@del org.apache.juneau.rest.client} - New package-level javadoc.
- Overview / Samples - New section.
- org.apache.juneau.swap / Stop Classes - New section.
- {@del org.apache.juneau.rest} - Extensive updates.