Release 5.2.0.0
Date: 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 aWritableinterface 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:
ConfigFileListenerSectionListenerEntryListener
Encodermethods have access to field names to use them as salt values.- The name of the default section is now
"default"
. Before it was justnull
. XorEncoderXOR 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. loggingLevel
class)parseString(String)
forName(String)
(e.g.Class
andCharset
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 asObject
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 @NameProperty and @ParentProperty annotations are provided for identifying methods for setting names and parent POJOs on child POJOs. For example, the config file
Sectionclass represents a section in a config file. It needs to know it's own name and have a link to theConfigFilethat it belongs to. With these new annotations, config files can be reconstructed using any of the parsers. -
New classes and interfaces:
Streamableinterface for identifying objects that can be serialized directly to an output stream.Writableinterface for identifying objects that can be serialized directly to a writer.StringObjectclass that can be used for delayed object serialization.ByteArrayCacheByteArrayInOutStreamFileUtilsThrowableUtilsStringVarMultipartStringVarWithDefault
-
New fields on
ObjectList:ObjectList.EMPTY_LIST
-
New fields and methods on
ObjectMap:ObjectMap.EMPTY_MAPObjectMap.getStringArray(String)ObjectMap.getStringArray(String,String[])ObjectMap.putIfNull(String,Object)ObjectMap.putIfEmpty(String,Object)
-
New methods in ArrayUtils:
ArrayUtils.contains(Object,Object[])ArrayUtils.indexOf(Object,Object[])ArrayUtils.toPrimitiveArray(Object)
-
New methods in
IOUtils:IOUtils.pipe(Reader,Writer)IOUtils.read(File)IOUtils.readFile(String)IOUtils.write(File,Reader)
-
New methods on
PojoRest:PojoRest.get(Class,String,Object)PojoRest.getString(String)PojoRest.getString(String,String)PojoRest.getInt(String)PojoRest.getInt(String,Integer)PojoRest.getLong(String)PojoRest.getLong(String,Long)PojoRest.getBoolean(String)PojoRest.getBoolean(String,Boolean)PojoRest.getMap(String)PojoRest.getMap(String,Map)PojoRest.getList(String)PojoRest.getList(String,List)getObjectMap(String)getObjectMap(String,ObjectMap)getObjectList(String)getObjectList(String,ObjectList)
-
New methods on
ProcBuilder:ProcBuilder.pipeTo(Writer,boolean)ProcBuilder.pipeTo(Writer)ProcBuilder.logTo(Writer,boolean)ProcBuilder.logTo(Writer)ProcBuilder.logTo(Level,Logger)ProcBuilder.maxExitStatus(int)
-
New methods on
StringUtils:StringUtils.isEmpty(Object)StringUtils.nullIfEmpty(String)StringUtils.base64EncodeToString(String)StringUtils.base64Encode(byte[])StringUtils.base64DecodeToString(String)StringUtils.base64Decode(String)StringUtils.generateUUID(int)StringUtils.trim(String)StringUtils.parseISO8601Date(String)StringUtils.replaceVars(String,Map)StringUtils.pathStartsWith(String,String)StringUtils.pathStartsWith(String,String[])
-
New
StringVar.doResolve(String)method. -
New
StringVarResolver.DEFAULTfield. -
Eliminated dependency on
javax.mail.internet.MimeUtility
by implementing our ownStringUtils.base64Encode(byte[])method. -
CalendarSwapandDateSwapclasses now handle blank input better. Returnsnull
instead of throwing an exception. -
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. -
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 HtmlDocSerializer.
-
Renamed
HtmlSchemaSerializertoHtmlSchemaDocSerializer. -
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).
-
Parser methods now check for
null
input. -
SerializerGroupandParserGroupignores serializers and parsers if they throwNoClassDefFoundErrors
. -
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_EXPANDEDserializer. -
Changes to
Args:getMainArg(int)
changed toArgs.getArg(int). Non-existent arguments are returned asnull
instead of blank strings. This is more inline with the behavior of the rest of the library.- New
Args.hasArg(int)method.
-
Removed
org.apache.juneau.utils.CharsetUtils
class. -
Removed
org.apache.juneau.utils.ConcurrentIdentityList
class. -
Fixed bug in
MultiIterableclass. -
PojoIntrospectormust now be instantiated with aReaderParser
. Simplifies the API on the class. -
PojoRestmust now be instantiated with aReaderParser
. Simplifies the API on the class. -
MessageBundleandSafeResourceMultiBundle
moved from server component. -
Several bug fixes and performance improvements in
StringVarResolver. -
Various enhancements to
TeeWriterandTeeOutputStream. -
Renamed
CharSettoAsciiSet. -
SerializerGroupandParserGroupnow ignoresNoClassDefFoundErrors
so that resources that include Jena support can continue to operate even if the Jena libraries are not present. -
New FileUtils.createTempFile(String) method.
-
New
PojoQuerymodified to handle bean getters that throw exceptions.
Client
-
Upgraded to use Apache HttpClient 4.5.
-
New classes:
AllowAllRedirectsHttpMethodResponsePatternSimpleX509TrustManagerSSLOpts
-
Removed
org.apache.juneau.rest.client.LaxRedirectStrategy
. Use HTTP Client equivalent. -
New methods on
RestCall:RestCall.addInterceptor(RestCallInterceptor)RestCall.pipeTo(Writer)RestCall.pipeTo(Writer,boolean)RestCall.pipeTo(String,Writer,boolean)RestCall.getWriter(String)RestCall.pipeTo(OutputStream)RestCall.pipeTo(OutputStream,boolean)RestCall.pipeTo(String,OutputStream,boolean)RestCall.getOutputStream(String)RestCall.byLines()RestCall.captureResponse()RestCall.successPattern(String)RestCall.failurePattern(String)RestCall.addResponsePattern(ResponsePattern)RestCall.run()- Renamed fromexecute()
.RestCall.getCapturedResponse()RestCall.getResponsePojoRest(Class)RestCall.getResponsePojoRest()RestCall.logTo(Level,Logger)RestCall.setConfig(RequestConfig)
-
New lifecycle listener methods on
RestCallInterceptor:RestCallInterceptor.onInit(RestCall)RestCallInterceptor.onClose(RestCall)
-
New methods on RestClient:
RestClient.setBasicAuth(String,int,String,String)RestClient.logTo(Level,Logger)RestClient.setRootUrl(String)RestClient.enableSSL(SSLOpts)RestClient.enableLaxSSL()RestClient.doCall(HttpMethod,Object,Object)RestClient.createHttpClientBuilder()
-
New passthrough methods on 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)setUserAgent(String)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
ReaderResourceclass. Represents the contents of a text file with convenience methods for resolvingStringVarvariables and adding HTTP response headers. REST Java methods can return instances of these to serializeReaders
containing text withStringVarResolvervariables in them. -
New
StreamResourceclass. REST Java methods can return instances of these to serializeOutputStreams
. -
Fixed a bug in the stack trace hash algorithm in
RestException. -
New methods in RestRequest:
RestRequest.getReaderResource(String)- ReplacesgetVarResource(String)
.RestRequest.getReaderResource(String,boolean)RestRequest.getReaderResource(String,boolean,String)
-
Changes in RestResponse:
- Don't set
Content-Encoding: identity
when no encoding is used. Some clients don't interpret it correctly.
- Don't set
-
New methods in
RestServlet:RestServlet.getChildClasses()- Programmatic equivalent to@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
JsoParserfromBasicRestServletandRestServletJenaDefault. These may represent a security risk if not handled correctly, so removed them as a precaution. -
Removed
RestServletProperties.REST_htDocsFolder
. Replaced with@RestResource(staticFiles). -
New annotations on
@RestResource.RestResource.stylesheet()RestResource.favicon()@RestResource(staticFiles)
-
Eliminated
org.apache.juneau.rest.jaxrs.JsonProvider
class. Some JAX-RS implementations use code scanning to find providers, so if you were usingDefaultJenaProvider
, it would pick upJsonProvider
as well. It's easy enough to create your own implementation if needed. -
OPTIONS pages now specify
consumes
andproduces
fields instead ofaccept
andcontentType
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 ofStreamable.WritableHandler- Allows REST Java methods to return instances ofWritable.
-
New DevOps stylesheet.
-
Servlet initialization and HTTP requests are now logged at
FINE
level. -
Added
abstract
modifier on variousRestServlet
subclasses to indicate that they're meant to be subclassed. -
New
RestUtils.trimPathInfo(StringBuffer,String,String)method.
Microservice
-
Completely revamped API.
-
New Microservice class that serves as a generic interface for microservices and their lifecycles.
-
New
RestMicroserviceclass 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. -
ResourceandResourceGroupclasses 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
BasicRestServletJenaclass 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:
- ConfigResource - REST resource for viewing and editing microservice config file.
- LogsResource - REST resource for viewing log files.
- SampleRootResource - Sample REST resource that contains the config and logs resource as children.
- 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
microservice- New package-level javadoc.config- New package-level javadoc.StringVarResolver- New documentation.client- New package-level javadoc.Overview / Samples- New section.org.apache.juneau.swap / Stop Classes- New section.rest- Extensive updates.