04 darwino concepts and utility classes
TRANSCRIPT
Darwino Concepts and Utility Classes
A overview of (some of) the classes available in Darwino
Darwino API Philosophy
• Darwino is designed as a set of ready to use and extensible APIs• The Darwino APIs must be portable across devices (JEE, Android, iOS…)
– It provides wrappers to similar device APIs– These wrappers must be lightweight and avoid unwanted dependencies
• The Darwino APIs are pragmatic– Make easy the most common things, but let the developer use more advanced
features when needed
Platform Object
• It gives information on the current runtime plaform• The Platform object is the entry points for many APIs
– Access to services, extensions…– Short to some services: logging, property, …
• Entry point to register plugins• Also carries an important flag: isDevelopment()
– Set explicitly or can be guessed by the runtime (ex: running in debug mode)– Can change some platform behaviors, like serving un-minimized js files for a
better debug experience
Plugins
• The core extension mechanism is based on plugin• A plugin is generally contributed by a library• It is based on the underlying platform extension mechanism
– Default core plugins are provided statically– On a regular JRE, they are provided
META-INF/service/com.darwino.commons.platform.Plugin
– On OSGi, there is a Darwino extension point<extension point="darwino.eclipse.darwinoPlugin"><service class="com.darwino.platform.web.PluginDarwinoWeb" /></extension>
– On mobile devices, they should be provided explicitly as Android does not support multiple files named the same in a single app
Services and Extensions
• Extensibility can have 2 forms– Services
• A service is a singleton that provides a function to the platform– Extensions
• A extension adds capability to an existing service
• Services/extensions are registered using a Plugin object– No common extension mechanism (OSGi, Java Services…) is available on all the
platforms– The Plugin object is registered using what the runtime platform provides
Notable Services
• Logging• Singleton• Properties• Console• …
Accessing a Service/Extension
• A service/extension is accessed though the Platform object public static<T> T getService(Class<T> serviceClass);public static<T> T getServiceUnchecked(Class<T> serviceClass); public static<T> void registerService(Class<T> serviceClass, T service);
public static<T> List<T> findExtensions(Class<T> serviceClass);}
Registering a Service/Extension
public class AppPlugin extends PluginImpl {public AppPlugin() {
super("SWT Application");}@Overridepublic void findExtensions(Class<?> serviceClass, List<Object>
extensions) {if(serviceClass==CommandsExtension.class) {
extensions.add(new AppHybridActions());}
}@Overridepublic void findDefaultService(Class<?> serviceClass) {…}
}
• A developer can implement– findExtensions() for both services and extension– findDefaultService() when a service is not returned by findExtensions()
Properties
• Darwino can be driven through properties, of the form<Key>=<value>
• Properties are accessed from the Platform objectPlatfom.getProperty(…)
• Properties are provided through extension points, and can come from any sources– Static property files bundled with the app– Static property files provided outside of the app– JNDI/LDAP directory, database, Java system properties…
Configuring Properties in a JEE Application
• The default JEE properties extension looks for:darwino.properties within the WEB-INF/ directory of the appdarwino.properties in the home of the application serverJNDI keys
• Example with TOMCAT
A Step Further: Managed Beans
• More complex configuration is provided using “Managed Beans”– A managed bean is a POJO with its lifecycle managed by the Darwino runtime
• The object is lazily created when needed– Similar to JSF or Spring beans
• Similarly to properties, managed beans are provided by extension points– Generally defined within XML files
• Default extension implementations find them in darwino-beans.xml files– The extensions are processed in order when looking for a bean
• Ex: WEB-INF/, Server Home, …
Finding a Managed Bean
• A managed bean is uniquely identified by a type and a name (with aliases)• The runtime searches for a bean using an array of names
– The beans extensions are traversed using every name and stopped when an implementation is found
– Ex: [“myapp”,”demo”,”default”]• The runtime first search for a bean named “myapp”, then ”demo”, then “default”
– This allows default beans, eventually superceeded by more contextual ones• A Darwino application provides a default list of names to search for
– Ex: database connection, directory, …
Managed Bean File Format <property name="tr">com.darwino.ThatClass</property>
<bean type="darwino/httptracer" name="tracer“class="com.darwino.BeanClass" alias="demo,default">
<property name="enabled">true</property> <bean class="com.darwino.MyClass"> <list name="tracers">
<bean class='${tr}'> </list> <map name="properties"> <entry key=‘name'>value</entry> </map>
<bean-ref name="bean-name "/> <bean-copy name="bean-name "/>
Property reusable across the file
Bean declaration
Class of the POJO
Aliases Bean content - properties• Primitives• Objects (beans)• Lists• Maps• Bean reference/copy
Darwino Utilities
• Darwino contains many utility classes• Located in com.darwino.commons• Have a look at these packages as they contains many time saver, tested
classes
String Utilities
• What you’ll see all over the Darwino source code– StringUtil.isEmpty()/isNotEmpty()
• Empty Strings & null are considered equals unless specified otherwise (rare)– StringUtil.format()
• Important for i18n purposes– StringUtil.split()
DateTime Utilities
• Format/parse ISO8601 date: long, Date, CalendarYYYY-MM-DDTHH:MM:SS[.mmm][TZ]TZ=Z, +/-HHMM, default is Z
• Format/parse date/time periodsEx: 1d, 5h7m, 5s
• Date and time ranges (useful for the Domino data replication)DateOnly, DateRange, DateOnlyRange…
• JsonUtil contains functions to parse these values
JSON Library
• Darwino comes with its own JSON library– There is no standard JSON library in Java, and we cannot use libraries that are
specific to a device (ex: Android’s org.json.*)• The Darwino library is optimized for performance and easy of use• Many ready to use capabilities are provided through the library
– JSON document for in memory JSON data– JSON parser and serializer– JSON path evaluator– JSON object serializers– … many others …
JSON Values
• The JSON Library provides a Factory that abstracts the JSON data– Useful to make some code independent from the library
• But Darwino mostly uses the JsonJavaFactory:– One instance is provided as a static Singleton– JSON Objects are JsonObject, Arrays are of JsonArray
• Std Java collections (Map<>, List<>) are also properly handled• Specialized JsonObject classes use custom Maps (LinkedMap, SortedMap…)
– Primitive values are Number (Integer, Double…), String and Boolean– Date/Time values are encoded/decoded as Strings with utilities in JsonUtil
• Used the ISO8801 format, e.g. YYYY-MM-DDTHH:MM:SS[.mmm][TZ]– Note that the default timezone is GMT, but this can be customized
JSON Parser and Serializer
• Available through the Factory or directly from the JsonObject/JsonArray
• Parser extensions– Supports member names inline or within single quotes– Supports JavaScript like comments within the text– Supports notifications as comments– Supports multiples objects from the same stream
JSON Utilities: JsonUtil
• Consistent JSON type management– Check is a value is valid– Parse/format all data types– Convert types (ex: string to number, …)
• Handling dates– Check if a value is a date, parse the ISO8601 Date
JSON Path
• Darwino features a JSON path engine available in both Java & JavaScripthttp://goessner.net/articles/JsonPath/
• Darwino caches the latest expressions to enhance the performance
JsonPath p = JsonPathFactory.get("a['b'].c");
public <T> T read(Object jsonObject) throws JsonException;public <T> T readValue(Object jsonObject) throws JsonException;public List<?> readAsList(Object jsonObject) throws JsonException;
public void write(Object jsonObject, Object value) throws JsonException;
JSON Navigator
• Navigating a document for extracting data is not always easy– Convert data types, check if a property is not null, access dates…
• Darwino provides a utility class that makes it easier for both JSON and XML payloads
JsonNav n = JsonNav.create(o);
n.get("topic_list").get("topics").flatten().forEach(new Handler() {@Overridepublic void handle(JsonNav nav) throws JsonException {
…}
}
JSON Over HTTP – Binary Encoding Optimization
• The Darwino services can serialize JSON as binary instead of Text– Faster encode/decode operations– Smaller payload as strings as not duplicated, number are optimized…– Easy to get data “as it comes”, useful when dealing with large data sets
• JSON binary encoding is only used when the requester explicitly asks for it– The request must contain the header:
• Accept: application/jsonb– The response will use the following response type
• Content-Type: application/jsonb
• This is automatically handled by the JSON client & service implementation, but can be disabled
JSON Over HTTP – Extensions
• JSON compacting– .pretty in the URL, or in DEV mode
• JSON progress– x-dwo-json-progress: true
XML Utilities
• Even though JSON is heavily used, XML style exists• Supplements the existing Java DOM APIs, regardless of the parser• DomUtil
– Format/parse XML documents to in memory DOM API– Many DOM Utilities
• XPathUtil– Encapsulate the XPath engine and provide easy to use methods, with a cache
• Other utilities: namespace ,node list…
XML Navigator
• Same than JSON navigator, but for XML• Makes the XML Document navigation easy, including namespace
XmlNav nav=XmlNav.create(doc,IbmConnections.namespaceCtx).get("a:feed").get("a:entry");
final Community community = new Community();nav.forEach(new XmlNav.Handler() {
@Overridepublic void handle(XmlNav nav) throws XmlException {
String id = nav.get("a:contributor").get("snx:userid").stringValue();
if(StringUtil.isNotEmpty(id)) {…
}}
}
HTTP Client
• Provides a easy access to HTTP based services with high level methods– Delegates to a platform implementation (URLConnection, Apache HTTP Client…)
• Supports the Darwino extensions, like binary JSON or JSON progress• Supports multiple authentication mechanisms• Supports chuncked request, gzip compression, SSL certificates• Examples:
Tasks
• Darwino provides the concepts of tasks that can be executed synchronously or asynchronously– Tasks have an execution context
• Execution parameters• Progress status• UI thread update
– A Callback can be called when the task execution is completed
TaskExecutorService svc = Platform.getService(TaskExecutorService.class);TaskExecutor<Void> ex = svc.createExecutor(true);ex.exec(new MyTask(instance,count));
Task Scheduler
• Tasks can be executed by a scheduler• ScheduledTask wraps a Task and add schedule information
• Darwino comes with a set of predefined schedulers– Very complete set of schedulers, with many options– Schedulers can be aggregated (multi cast)– Custom schedulers can be created
• Tasks can be scheduled through managed beans
TaskScheduler sch = Platform.getService(TaskScheduler.class);ScheduledTask t1 = sch.scheduleTask(new MyTask(…), new MyScheduler(…));
<bean type="darwino/scheduler" name="feedConsumer" class="com.darwino.commons.tasks.scheduler.bean.SchedulerBean"> <property name="enabled">${socialanalyzer.feedConsumer.enabled=true}</property> <bean name="scheduler" class="com.darwino.commons.tasks.scheduler.schedulers.IntervalScheduler"> <property name="interval">${socialanalyzer.feedConsumer.interval=1h}</property> </bean> <bean name="task" class="com.darwino.socialanalyzer.feeds.FeedConsumerTask"/></bean>
Logging
• JRE 1.4 provided a logging APIs but this is incomplete– Other Platforms might have different APIs (ex: Android)
• Very lightweight, no dependency (slf4j…)• Easy to use method with I18N formatting• Logging groups
– Define hierarchically– A good pattern is to define all the groups in a single class to get them initialized
early– Groups can be discovered at runtime
• Helps debugging and settings the groups dynamically• Darwino commands will provide methods
Exception Handling
• All the Darwino exceptions are based on the same base class– AbstractException, AbstractRuntimeException
• These classes enforce the exception chaining mechanism– The first parameter of a constructor is (Throwable cause)
• It provides extra information for debugging purposes– IExceptionEx provides a JSON Map of extra information to be dumped
Profiler
• Darwino features a code profiler used to find hotspots in the code• The profiler acts at a higher level, logical function
– Complimentary with the jvm lower level ones (Yourkit…)• The developer decides what to profile• The performance overhead is insignificant
– All the base functions in Darwino provide it• REST services, tasks, SQL queries…
• Activated by APIs– Available web module to deal with it– Default set of commands available as well
if(Profiler.isEnabled()) { ProfilerAggregator agg = Profiler.startProfileBlock(“name”,”context”); long ts = Profiler.getCurrentTime(); try {
executeCode(); } finally { Profiler.endProfileBlock(agg,ts); }} else {
executeCode();}
Internationalization (I18N)
• Based on GNU GetText (https://www.gnu.org/software/gettext/)– Well known, many tools available for translators, maven plugin…
• I18NContext– Set of resource bundles for a Locale
• I18NContextFactory– Set of I18NContext, organized by Locale
• I18NLocaleService– Access to the current Locale, global of user specific
• DwoResources helper– _t(text), _tc(key,text)– _tu(text), _tuc(key,text)
Darwino Applications
• A Darwino application is made of layers– Each layer provides more high level, ready to use features
• The top layer provides the Darwino platform on top of the utility libraries• The Darwino platform provides features/services in a device indeendant
format (generic APIs):– Application relative objects: DarwinoApplication & DarwinoContext– Application description using a Manifest class– User authentication– Access to the JSON store– …
Darwino Application Object
• Every Darwino application has one, and only one, DarwinoApplication instance
• This instance is created when the application is started and remains available until the application is closed
Darwino Context Object
• A DarwinoContext contains information on the current request– Ex: current user when the application is a JEE application
• A new application object is created every time it is necessary and discarded when the context disappears– Ex: every request on a JEE application creates/destroys a context object
• For single user applications, like Mobile applications, the object is created once and remain valid for the application lifetime– But it makes the APIs consistent, whenever it runs on a server or on a device
Application Manifest
• The application manifest is a developer provided class that contains important information about the application
• The runtime use this class extensively• A manifest is actually composed of:
– A DarwinoManifest object, that is common across devices– Some specialized manifest objects, providing information for a particular platform
• Ex: JEE manifest, Android manifest, iOS manifest…
<Image Slide>
Thank you for your attention!