http://git-wip-us.apache.org/repos/asf/polygene-website/blob/bb9c9971/content/java/2017/state-modeling.html ---------------------------------------------------------------------- diff --git a/content/java/2017/state-modeling.html b/content/java/2017/state-modeling.html new file mode 100644 index 0000000..237437e --- /dev/null +++ b/content/java/2017/state-modeling.html @@ -0,0 +1,250 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>Polygene⢠and state modeling</title><meta name="generator" content="DocBook XSL Stylesheets V1.78.1" /><link rel="home" href="index.html" title="" /><link rel="up" href="intro.html" title="Introduction" /><link rel="prev" href="what-s-an-object-anyway.html" title="Whatâs an Object anyway?" /><link rel="next" href="related.html" title="Related publications & projects" /> + + + <meta charset="utf-8"> + <meta http-equiv="X-UA-Compatible" content="IE=edge"> + <meta name="viewport" content="width=device-width, initial-scale=1"> + <!-- The above 3 meta tags *must* come first in the head; any other head content must come *after* these tags --> + <meta name="description" content=""> + <meta name="author" content=""> + <link rel="icon" href="../../favicon.ico"> + + <title>Starter Template for Bootstrap</title> + + <!-- Bootstrap core CSS --> + <link href="bootstrap-3.3.7/css/bootstrap.min.css" rel="stylesheet"> + + <!-- IE10 viewport hack for Surface/desktop Windows 8 bug --> + <link href="css/ie10-viewport-bug-workaround.css" rel="stylesheet"> + + <!-- Custom styles for this template --> + <link href="css/polygene-ng.css" rel="stylesheet"> + + <!-- Just for debugging purposes. Don't actually copy these 2 lines! --> + <!--[if lt IE 9]><script src="../../assets/js/ie8-responsive-file-warning.js"></script><![endif]--> + <script src="js/ie-emulation-modes-warning.js"></script> + + <!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries --> + <!--[if lt IE 9]> + <script src="https://oss.maxcdn.com/html5shiv/3.7.3/html5shiv.min.js"></script> + <script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script> + <![endif]--> + +<!-- favicon --> + +<link rel="shortcut icon" href="http://polygene.apache.org/favicon.ico" type="image/vnd.microsoft.icon" /> +<link rel="icon" href="http://polygene.apache.org/favicon.ico" type="image/x-icon" /> + +<!-- style --> + +<link href="css/shCore.css" rel="stylesheet" type="text/css" /> +<link href="css/shCoreEclipse.css" rel="stylesheet" type="text/css" /> +<link href="css/shThemeEclipse.css" rel="stylesheet" type="text/css" /> +<!--<link href="css/polygene.css" rel="stylesheet" type="text/css" />--> + +<!-- Syntax Highlighter --> + +<script type="text/javascript" src="js/shCore.js"></script> +<script type="text/javascript" src="js/shBrushJava.js"></script> +<script type="text/javascript" src="js/shBrushScala.js"></script> +<script type="text/javascript" src="js/shBrushJScript.js"></script> +<script type="text/javascript" src="js/shBrushBash.js"></script> +<script type="text/javascript" src="js/shBrushPlain.js"></script> +<script type="text/javascript" src="js/shBrushXml.js"></script> +<script type="text/javascript" src="js/shBrushGroovy.js"></script> +<script type="text/javascript" src="js/shBrushPython.js"></script> +<script type="text/javascript" src="js/shBrushRuby.js"></script> +<script type="text/javascript" src="js/shBrushCSharp.js"></script> + +<script type="text/javascript"> + SyntaxHighlighter.defaults['tab-size'] = 4; + SyntaxHighlighter.defaults['gutter'] = false; + SyntaxHighlighter.defaults['toolbar'] = false; + SyntaxHighlighter.all() +</script> + +<!-- JQuery --> + +<script type="text/javascript" src="js/jquery-1.6.4.min.js"></script> + +<!-- Image Scaler --> + +<script type="text/javascript" src="js/imagescaler.js"></script> + +<!-- Table Styler --> + +<script type="text/javascript" src="js/tablestyler.js"></script> + +<!-- Apache Polygene WebSite Progressive Enhancement --> + +<link href="css/progressive-enhancement.css" rel="stylesheet" type="text/css" /> +<script type="text/javascript" src="js/jquery.scrollTo-1.4.2.js"></script> +<script type="text/javascript" src="js/progressive-enhancement.js"></script> + +<!-- Analytics --> + <script type="text/javascript"> + var _gaq = _gaq || []; + _gaq.push(['_setAccount', 'UA-62007352-1']); + _gaq.push(['_trackPageview']); + + (function() { + var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true; + ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js'; + var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s); + })(); + </script> + + </head><body><div xmlns="" xmlns:exsl="http://exslt.org/common" class="logo"><a href="index.html"><img src="images/logo-standard.png" /></a></div><nav xmlns="" xmlns:exsl="http://exslt.org/common" class="navbar navbar-inverse navbar-fixed-top"><div class="container"><div class="navbar-header"><a class="navbar-brand" href="#">Apache<br />Polygene + </a></div><div id="navbar" class="collapse navbar-collapse"><span class="nav navbar-nav"><div xmlns="http://www.w3.org/1999/xhtml" class="toc"><dl class="toc"><dt><span class="section"><a href="index.html#home">Polygeneâ¢</a></span></dt><dt><span class="section"><span xmlns="" href="intro.html">Introduction</span></span></dt><dt><span class="section"><a href="tutorials.html">Tutorials</a></span></dt><dt><span class="section"><a href="javadocs.html">Javadoc</a></span></dt><dt><span class="section"><a href="samples.html">Samples</a></span></dt><dt><span class="section"><a href="core.html">Core</a></span></dt><dt><span class="section"><a href="libraries.html">Libraries</a></span></dt><dt><span class="section"><a href="extensions.html">Extensions</a></span></dt><dt><span class="section"><a href="tools.html">Tools</a></span></dt><dt><span class="section"><a href="glossary.html">Glossary </a></span></dt></dl></div></span></div></div></nav><div xmlns="" xmlns:exsl="http://exslt .org/common" class="sidenav"><div xmlns="http://www.w3.org/1999/xhtml" class="toc"><dl class="toc"><dt><span class="section"><a href="intro.html#highlights">Highlights</a></span></dt><dt><span class="section"><a href="tools-shell.html">Polygene Generator</a></span></dt><dt><span class="section"><a href="introduction-background.html">Background</a></span></dt><dt><span class="section"><a href="what-is-cop.html">What is COP?</a></span></dt><dt><span class="section"><a href="what-s-an-object-anyway.html">Whatâs an Object anyway?</a></span></dt><dt><span class="section"><span xmlns="" href="state-modeling.html">Polygene⢠and state modeling</span></span></dt><dt><span class="section"><a href="related.html">Related publications & projects</a></span></dt></dl></div></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a id="state-modeling"></a>Polygene⢠and state modeling</h3></div></div></div><p>(From Rickard Obergâs blog, <a class="ulink" href="http:/ /www.jroller.com/rickard/entry/qi4j_and_state_modeling" target="_top">http://www.jroller.com/rickard/entry/qi4j_and_state_modeling</a>, 2009-02-19)</p><p>In the Polygene⢠project we strive to being able to express our domain as directly as possible, with as little translation +as possible between how we think about a domain and how it is actually coded. +This then affects our entire view of how application frameworks should be constructed, and what we consider good and +bad ways of implementing certain features.</p><p>One part which is a good example of this is persistent state modeling. In other approaches and frameworks one would +typically use POJOs for the objects, and then plain class fields for references, collections and properties. +But during modeling these are not the words we use. +If POJOs are used for both Entities and Values, which have radically different semantics, we have to always translate +in our heads when talking about them, always keeping mind what the POJO is doing in any particular context. +In Domain Driven Design terms, POJOs are not in our Ubiquitous Language.</p><p>From a DDD perspective we want to talk about Entities and Values, Properties and Associations. +If our code does not reflect this, then there is translation going on, and translation inevitably leads to information loss. +In Polygeneâ¢, where Composites and not Objects, are the basic construct, we have created specialized forms to model these +concepts more explicitly. +We have EntityComposites and ValueComposites, each with different ways of creating them and managing them. +Both EntityComposites and ValueComposites can then have Properties, as first-class objects, but Properties in +ValueComposites are always immutable.</p><div class="section"><div class="titlepage"><div><div><h4 class="title"><a id="_entities"></a>Entities</h4></div></div></div><p>Hereâs an example of how you could define an EntityComposite:</p><pre class="programlisting brush: java">interface PersonEntity + extends EntityComposite +{ + Property<String> givenName(); + Property<String> surName(); +} + +</pre><p>With these few lines you have done what would have taken a whole lot more effort using POJOs, and what you want to +express is very explicit. +To define a property you would have had to write a field and two accessors, and if you use interfaces then those +accessors would have to be duplicated.</p><p>The EntityComposite base interface also includes an identity property for you, as thatâs an intrinsic feature of +Entities, so thatâs all taken care of. +So if you speak about Entities in your domain discussions, each having Properties, then you can put that down in +code pretty much as-is. +This is, to me, a huge advantage over other ways of doing it, including POJO modeling (which lose clarity), UML +modeling (which has roundtrip problems), DSL modeling (which lose tools support), and whatnot.</p></div><div class="section"><div class="titlepage"><div><div><h4 class="title"><a id="_roles"></a>Roles</h4></div></div></div><p>If you want to get picky about it, the above example is probably not how you would model Person. Having a name is +just one role that a Person has to play, and since Composite Oriented Programming is all about using roles and +context instead of classes you would probably do something like this instead:</p><pre class="programlisting brush: java">interface Nameable +{ + @UseDefaults Property<String> givenName(); + @UseDefaults @Optional Property<String> surName(); +} + +interface PersonEntity + extends Nameable, EntityComposite +{} +</pre><p>Iâve extracted the ability to be Named to its own interface, and let my domain Entity extend it. +This way client code can check for "x instanceof Nameable" rather than "x instanceof PersonEntity", and then do +something intelligent with it. +By doing this, not only has Nameable become a reusable interface, but the client code that understands it has also +become reusable for all domain objects in your model that uses it!</p><p>Iâve also marked both properties as @UseDefaults. +What does this do? +Well, if you have string properties they have the annoying property of being null to begin with, compared to ints +and longs which default to 0. +We figured that this was such a useful thing that we wanted to be able to mark our properties as being able to have +their initial values be set to a default, for the type. +For Strings this is the empty string, for primitives they are what you would expect. +For Collections they are set to empty collections of the type indicated. +"@UseDefaults Property<List<String>> addresses();" would be initialized to an empty ArrayList, for example.</p><p>In addition I have set surName() to be @Optional. +In Polygene⢠we have defined all properties to be not-null as the default, and the same goes for all parameters in method +invocations. +If you explicitly want to allow properties to be null, so that for example "Madonna" would be an acceptable name, +then you can mark it as @Optional. +We prefer @Optional to @Nullable since it better expresses the intent from a domain perspective. +Avoiding technical terms as much as possible is a another goal (which is damn hard to reach!).</p></div><div class="section"><div class="titlepage"><div><div><h4 class="title"><a id="_values"></a>Values</h4></div></div></div><p>If you want to get really picky about it, not even the above would be a real example. +You may want to encapsulate the two properties into one value instead, so that you can more easily perform validation +checks when they are updated. What you want are ValueComposites:</p><pre class="programlisting brush: java">interface NameValue + extends ValueComposite +{ + @UseDefaults Property<String> givenName(); + @UseDefaults @Optional Property<String> surName(); +} + +interface Nameable +{ + Property<NameValue> name(); +} +</pre><p>Normally if you want a property to be immutable, meaning, you can set an initial value but not change it later, you +would have to mark the Property as @Immutable. +But since NameValue extends ValueComposite, which itself is marked with @Immutable, this is implicit for all subtypes +of ValueComposite, and thereâs no way to "opt out" of it.</p><p>By introducing one more level in the state model you have created an easy way to access the name as a whole and hand +it around the system, instead of as two separate properties. +Since it is immutable you are also ensured that noone can change it without going through the Entity, and you can +also share instances of the name without having to worry about thread-safety.</p></div><div class="section"><div class="titlepage"><div><div><h4 class="title"><a id="_privatizing_state"></a>Privatizing state</h4></div></div></div><p>The above is already a great step ahead in terms of how you can model your state more easily than having to use POJOs +to sort of "fake" the features Iâm describing above, and thereâs also a ton of cool features and consequences of the +whole thing Iâm skipping here, for brevity. +One of the problems with POJO models that usually come up is that your getters and setters get exposed to clients, +and so functionality tend to not be put in the Entities, but rather in services and helper code, thereby scattering +the Entity into a bunch of places. +What should have been a neat and tidy little package is instead a anorectic little thing whose guts lay splashed +around your code, looking all soggy and unappetizing.</p><p>What to do about this? +One of the great inventions of Polygeneâ¢, I believe, is the notion of private mixins. +That we can have mixins in an object which are explicitly HIDDEN from usage outside of it. +How can we use this for state modeling? +What youâd want to do is to model the state of an Entity as a private mixin, which is hidden from clients, and then +you write role mixins which map domain methods to that internal state. Hereâs an example:</p><pre class="programlisting brush: java">@Mixins(ListablePersonMixin.class) +interface PersonEntity + extends Listable, EntityComposite {} + +interface PersonState + extends Nameable {} + +public class ListablePersonMixin + implements Listable +{ + @This PersonState person; + + @Override + public String listName() + { + String fullName = person.name().get().givenName().get(); + String sn = person.name().get().surName().get(); + if (sn != null) fullName += " "+sn; + return fullName; + } +} + +interface Listable +{ + public String listName(); +} +</pre><p>Neat huh? +@This is a dependency injection annotation, but rather than the usual generic annotations like "@Inject" and friends, +this one actually has a meaningful scope, that is, it requires that "this Entity" implements PersonState. +The reference, as it is not extended by PersonEntity, is not visible to clients of the Entity and is hence a +private mixin. +Furthermore, all of a sudden your client code doesnât even care if your domain object is Nameable, but rather if it +is Listable. +Cool! +So you can make a UI widget for listing "stuff" that only requires that your thingie is Listable, rather than being +a PersonEntity or Nameable.</p><p>For extra credit you could move the construction of "fullName" into a method on the NameValue, so that the value is +not only a dumb data container, but can also perform useful operations on itself. +And for the performance aware, donât worry, the mixin is lazy-loaded, so if the particular usecase handling the +Entity doesnât need the "Listable" interface the mixin will never be instantiated.</p><p>And so much moreâ¦</p><p>The above is just a small taste of what you can do with state modeling in Polygeneâ¢. +There is also support for associations and many-associations, the notion of aggregates, and a complete pluggable +system for persistence and indexing/querying of data. +To end with, hereâs a sample of how some other state modeling concepts can be expressed in Polygeneâ¢:</p><pre class="programlisting brush: java">interface PersonEntity + extends EntityComposite +{ + Association<PersonEntity> father(); + @Optional Association<PersonEntity> spouse(); + ManyAssociation<PersonEntity> children(); + @Aggregated ManyAssociation<BookNoteEntity> favouriteBooks(); +} + +interface BookNoteEntity + extends EntityComposite +{ + Property<String> note(); + Association<BookEntity> book(); +} + +</pre><p>I hope they are self-explanatory.</p><p>My hope is that with Composite Oriented Programming and Polygene⢠we can come one step closer to being able to express our +domain as clearly as possible in code.</p></div></div><footer xmlns="" xmlns:exsl="http://exslt.org/common" class="footer"><div class="container"><p class="text-muted">Copyright © 2017 The Apache Software Foundation, Licensed under the <a href="http://www.apache.org/licenses/" target="_blank">Apache License, Version 2.0</a>. + Apache Polygene, Polygene, Apache, the Apache feather logo, and the Apache Polygene project logo are + trademarks of The Apache Software Foundation. + All other marks mentioned may be trademarks or registered trademarks of their respective owners. + </p></div></footer><script xmlns="" xmlns:exsl="http://exslt.org/common" src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script><script xmlns="" xmlns:exsl="http://exslt.org/common">window.jQuery || document.write('<script src="js/jquery-1.6.4.min.js"></script>')</script><script xmlns="" xmlns:exsl="http://exslt.org/common" src="https://cdnjs.cloudflare.com/ajax/libs/tether/1.4.0/js/tether.min.js" integrity="sha384-DztdAPBWPRXSA/3eYEEUWrWCy7G5KFbe8fFjk5JAIxUYHKkDx6Qin1DkWx51bBrb" crossorigin="anonymous"></script><script xmlns="" xmlns:exsl="http://exslt.org/common" src="bootstrap-3.3.7/js/bootstrap.min.js"></script><script xmlns="" xmlns:exsl="http://exslt.org/common" src="js/ie10-viewport-bug-workaround.js"></script></body></html> \ No newline at end of file
http://git-wip-us.apache.org/repos/asf/polygene-website/blob/bb9c9971/content/java/2017/ten-minutes-intro.html ---------------------------------------------------------------------- diff --git a/content/java/2017/ten-minutes-intro.html b/content/java/2017/ten-minutes-intro.html new file mode 100644 index 0000000..9c2b24a --- /dev/null +++ b/content/java/2017/ten-minutes-intro.html @@ -0,0 +1,201 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>Polygene⢠in 10 minutes</title><meta name="generator" content="DocBook XSL Stylesheets V1.78.1" /><link rel="home" href="index.html" title="" /><link rel="up" href="tutorials.html" title="Tutorials" /><link rel="prev" href="two-minutes-intro.html" title="Polygene⢠in 2 minutes" /><link rel="next" href="thirty-minutes-intro.html" title="Polygene⢠in 30 minutes" /> + + + <meta charset="utf-8"> + <meta http-equiv="X-UA-Compatible" content="IE=edge"> + <meta name="viewport" content="width=device-width, initial-scale=1"> + <!-- The above 3 meta tags *must* come first in the head; any other head content must come *after* these tags --> + <meta name="description" content=""> + <meta name="author" content=""> + <link rel="icon" href="../../favicon.ico"> + + <title>Starter Template for Bootstrap</title> + + <!-- Bootstrap core CSS --> + <link href="bootstrap-3.3.7/css/bootstrap.min.css" rel="stylesheet"> + + <!-- IE10 viewport hack for Surface/desktop Windows 8 bug --> + <link href="css/ie10-viewport-bug-workaround.css" rel="stylesheet"> + + <!-- Custom styles for this template --> + <link href="css/polygene-ng.css" rel="stylesheet"> + + <!-- Just for debugging purposes. Don't actually copy these 2 lines! --> + <!--[if lt IE 9]><script src="../../assets/js/ie8-responsive-file-warning.js"></script><![endif]--> + <script src="js/ie-emulation-modes-warning.js"></script> + + <!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries --> + <!--[if lt IE 9]> + <script src="https://oss.maxcdn.com/html5shiv/3.7.3/html5shiv.min.js"></script> + <script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script> + <![endif]--> + +<!-- favicon --> + +<link rel="shortcut icon" href="http://polygene.apache.org/favicon.ico" type="image/vnd.microsoft.icon" /> +<link rel="icon" href="http://polygene.apache.org/favicon.ico" type="image/x-icon" /> + +<!-- style --> + +<link href="css/shCore.css" rel="stylesheet" type="text/css" /> +<link href="css/shCoreEclipse.css" rel="stylesheet" type="text/css" /> +<link href="css/shThemeEclipse.css" rel="stylesheet" type="text/css" /> +<!--<link href="css/polygene.css" rel="stylesheet" type="text/css" />--> + +<!-- Syntax Highlighter --> + +<script type="text/javascript" src="js/shCore.js"></script> +<script type="text/javascript" src="js/shBrushJava.js"></script> +<script type="text/javascript" src="js/shBrushScala.js"></script> +<script type="text/javascript" src="js/shBrushJScript.js"></script> +<script type="text/javascript" src="js/shBrushBash.js"></script> +<script type="text/javascript" src="js/shBrushPlain.js"></script> +<script type="text/javascript" src="js/shBrushXml.js"></script> +<script type="text/javascript" src="js/shBrushGroovy.js"></script> +<script type="text/javascript" src="js/shBrushPython.js"></script> +<script type="text/javascript" src="js/shBrushRuby.js"></script> +<script type="text/javascript" src="js/shBrushCSharp.js"></script> + +<script type="text/javascript"> + SyntaxHighlighter.defaults['tab-size'] = 4; + SyntaxHighlighter.defaults['gutter'] = false; + SyntaxHighlighter.defaults['toolbar'] = false; + SyntaxHighlighter.all() +</script> + +<!-- JQuery --> + +<script type="text/javascript" src="js/jquery-1.6.4.min.js"></script> + +<!-- Image Scaler --> + +<script type="text/javascript" src="js/imagescaler.js"></script> + +<!-- Table Styler --> + +<script type="text/javascript" src="js/tablestyler.js"></script> + +<!-- Apache Polygene WebSite Progressive Enhancement --> + +<link href="css/progressive-enhancement.css" rel="stylesheet" type="text/css" /> +<script type="text/javascript" src="js/jquery.scrollTo-1.4.2.js"></script> +<script type="text/javascript" src="js/progressive-enhancement.js"></script> + +<!-- Analytics --> + <script type="text/javascript"> + var _gaq = _gaq || []; + _gaq.push(['_setAccount', 'UA-62007352-1']); + _gaq.push(['_trackPageview']); + + (function() { + var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true; + ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js'; + var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s); + })(); + </script> + + </head><body><div xmlns="" xmlns:exsl="http://exslt.org/common" class="logo"><a href="index.html"><img src="images/logo-standard.png" /></a></div><nav xmlns="" xmlns:exsl="http://exslt.org/common" class="navbar navbar-inverse navbar-fixed-top"><div class="container"><div class="navbar-header"><a class="navbar-brand" href="#">Apache<br />Polygene + </a></div><div id="navbar" class="collapse navbar-collapse"><span class="nav navbar-nav"><div xmlns="http://www.w3.org/1999/xhtml" class="toc"><dl class="toc"><dt><span class="section"><a href="index.html#home">Polygeneâ¢</a></span></dt><dt><span class="section"><a href="intro.html">Introduction</a></span></dt><dt><span class="section"><span xmlns="" href="tutorials.html">Tutorials</span></span></dt><dt><span class="section"><a href="javadocs.html">Javadoc</a></span></dt><dt><span class="section"><a href="samples.html">Samples</a></span></dt><dt><span class="section"><a href="core.html">Core</a></span></dt><dt><span class="section"><a href="libraries.html">Libraries</a></span></dt><dt><span class="section"><a href="extensions.html">Extensions</a></span></dt><dt><span class="section"><a href="tools.html">Tools</a></span></dt><dt><span class="section"><a href="glossary.html">Glossary </a></span></dt></dl></div></span></div></div></nav><div xmlns="" xmlns:exsl="http://exslt .org/common" class="sidenav"><div xmlns="http://www.w3.org/1999/xhtml" class="toc"><dl class="toc"><dt><span class="section"><a href="tutorials.html#_overview">Overview</a></span></dt><dt><span class="section"><a href="two-minutes-intro.html">Polygene⢠in 2 minutes</a></span></dt><dt><span class="section"><span xmlns="" href="ten-minutes-intro.html">Polygene⢠in 10 minutes</span></span></dt><dt><span class="section"><a href="thirty-minutes-intro.html">Polygene⢠in 30 minutes</a></span></dt><dt><span class="section"><a href="howto-depend-on-polygene.html">Depend on Polygeneâ¢</a></span></dt><dt><span class="section"><a href="howto-assemble-application.html">Assemble an Application</a></span></dt><dt><span class="section"><a href="tut-composites.html">Transient Composites Tutorial</a></span></dt><dt><span class="section"><a href="tut-services.html">Services Composites Tutorial</a></span></dt><dt><span class="section"><a href="howto-contextual-fragments.html">Use contextual frag ments</a></span></dt><dt><span class="section"><a href="howto-leverage-properties.html">Leverage Properties</a></span></dt><dt><span class="section"><a href="howto-create-constraint.html">Create a Constraint</a></span></dt><dt><span class="section"><a href="howto-create-concern.html">Create a Concern</a></span></dt><dt><span class="section"><a href="howto-create-sideeffect.html">Create a SideEffect</a></span></dt><dt><span class="section"><a href="howto-create-entity.html">Create an Entity</a></span></dt><dt><span class="section"><a href="howto-configure-service.html">Configure a Service</a></span></dt><dt><span class="section"><a href="howto-invocation-annotation.html">Use @Invocation</a></span></dt><dt><span class="section"><a href="build-system.html">Polygene⢠Build System</a></span></dt><dt><span class="section"><a href="community-docs.html">Polygene⢠Documentation</a></span></dt><dt><span class="section"><a href="releasing-apache.html">Releasing Polygeneâ¢</a></span></dt>< /dl></div></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a id="ten-minutes-intro"></a>Polygene⢠in 10 minutes</h3></div></div></div><div class="tip" style="margin-left: 0.5in; margin-right: 0.5in;"><h3 class="title">Tip</h3><p>Theses tutorials are based on actual code found in the <code class="literal">tutorials/</code> directory of the +<a class="ulink" href="https://polygene.apache.org/download.html" target="_top">Polygene⢠SDK sources</a>. You should start your favorite editor and find the code related to +this tutorial, run it and play with it.</p></div><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"> +Polygene⢠does not introduce any new programming language, no additional compilers needed and all your existing tools + work just like before. It is pure Java. +</li><li class="listitem"> +Polygene⢠works with Composites. +</li><li class="listitem"> +The equivalent of an Object instance in OOP, is a Composite instance in Polygeneâ¢. +</li><li class="listitem"> +Composites are constructed from Fragments. +</li><li class="listitem"> +Fragments are Mixins, Concerns, Constraints and SideEffects. +</li><li class="listitem"> +Only Mixins carry Composite state. The others are shared between Composite instances. +</li></ul></div><p>If you want to reproduce whatâs explained in this tutorial, remember to depend on the Core Runtime artifact that depends +on Core API, Core SPI, and Core Bootstrap:</p><div class="table"><a id="idm745"></a><p class="title"><strong>Table 2. Artifact</strong></p><div class="table-contents"><table summary="Artifact" border="1"><colgroup><col class="col_1" /><col class="col_2" /><col class="col_3" /></colgroup><thead><tr><th align="left" valign="top">Group ID</th><th align="left" valign="top">Artifact ID</th><th align="left" valign="top">Version</th></tr></thead><tbody><tr><td align="left" valign="top"><p>org.apache.polygene.core</p></td><td align="left" valign="top"><p>org.apache.polygene.core.runtime</p></td><td align="left" valign="top"><p>0</p></td></tr></tbody></table></div></div><br class="table-break" /><p>Moreover, youâll need an EntityStore for persistence and an Indexing engine for querying. Choose among the available +implementations listed in the <a class="xref" href="extensions.html" title="Extensions">Extensions</a> section.</p><p>See the <a class="xref" href="howto-depend-on-polygene.html" title="Depend on Polygeneâ¢">Depend on Polygeneâ¢</a> tutorial for details.</p><p>Composition is done with Java interfaces and Annotations. Example;</p><pre class="programlisting brush: java">@Concerns( { PurchaseLimitConcern.class, InventoryConcern.class } ) +public interface OrderEntity + extends Order, Confirmable, + HasSequenceNumber, HasCustomer, HasLineItems, + EntityComposite +{ +} +</pre><p>This Composite is potentially complete. The Composite interface has a Mixin declared which is always present, the +PropertyMixin, which will handle all properties we use. The two Concerns are interceptors that are placed on the +methods that they declare, for instance;</p><pre class="programlisting brush: java">public class InventoryConcern extends ConcernOf<Order> + implements Order +{ + @Service + private InventoryService inventory; + + @Override + public void addLineItem( LineItem item ) + { + String productCode = item.productCode().get(); + int quantity = item.quantity().get(); + inventory.remove( productCode, quantity ); + next.addLineItem( item ); + } + + @Override + public void removeLineItem( LineItem item ) + { + String productCode = item.productCode().get(); + int quantity = item.quantity().get(); + inventory.add( productCode, quantity ); + next.removeLineItem( item ); + } +} +</pre><p>Extending the ConcernOf is a convenience mechanism, instead of an explicit @ConcernFor annotation on a private field, +which can be used in rare occasions when you are not able to extend. This base class defines the <code class="literal">next</code> field, which is +set up by the Polygene⢠runtime and points to the next fragment in the call stack.</p><p>We can also see that the InventoryService is provided to the concern, which is done with dependency injection. Polygene⢠+also supports dependency injection via constructors and methods.</p><p>The above example is obviously doing persistence, and we have no code handling this. But Polygene⢠supports persistence +directly in its Core, and it is taken care of by Polygeneâ¢, since it is declared as an EntityComposite. +Nothing else is needed, provided that the Polygene⢠Runtime has been setup with one or more persisted EntityStores. But +we have a naming convention that EntityComposites have "Entity" as the suffix in its name.</p><p>There are other built-in Composite subtypes as well, such as ValueComposite and ServiceComposite. This distinction helps +both to communicate intent as well as having more precisely defined functionality.</p><p>Now, letâs say that we want to send a mail to <a class="ulink" href="mailto:[email protected]" target="_top">[email protected]</a> when the order is confirmed. This is a SideEffect, and +will execute after the Constraints, Concerns and Mixins. We add the SideEffect to the OrderEntity;</p><pre class="programlisting brush: java">@SideEffects( MailNotifySideEffect.class ) +@Concerns( { PurchaseLimitConcern.class, InventoryConcern.class } ) +public interface OrderEntity + extends Order, Confirmable, + HasSequenceNumber, HasCustomer, HasLineItems, + EntityComposite +{ +</pre><p>The SideEffect implementation is fairly simple.</p><pre class="programlisting brush: java">public abstract class MailNotifySideEffect extends SideEffectOf<Confirmable> + implements Confirmable +{ + @Service + private MailService mailer; + + @This + private HasLineItems hasItems; + + @This + private HasCustomer hasCustomer; + + @Override + public void confirm() + { + StringBuilder builder = new StringBuilder(); + builder.append( "An Order has been made.\n\n\n" ); + builder.append( "Customer:" ); + builder.append( hasCustomer.name().get() ); + builder.append( "\n\nItems ordered:\n" ); + for( LineItem item : hasItems.lineItems().get() ) + { + builder.append( item.name().get() ); + builder.append( " : " ); + builder.append( item.quantity().get() ); + builder.append( "\n" ); + } + mailer.send( "[email protected]", builder.toString() ); + } +} +</pre><p>The MailService is dependency injected, as we have seen before.</p><p>@This is telling Polygene⢠that the SideEffect needs a reference to the Composite instance that it belongs to.</p><p>By asking for both the HasCustomer and the HasLineItems types, we get type-safety and donât need to bother with casts. +In fact, Polygene⢠will ensure that you canât even cast the <code class="literal">hasCustomer</code> instance to the HasLineItems type.</p><p>By not referencing the aggregated interface OrderEntity, we reduce the coupling of this SideEffect and it can be used +in any other Composite where the HasCustomer and HasLineItems combination is used, for instance in an InvoiceEntity.</p><p>So, build the report, send it via the MailService.</p><div class="section"><div class="titlepage"><div><div><h4 class="title"><a id="_conclusion"></a>Conclusion</h4></div></div></div><p>In this short introduction, we have covered the essence of Polygeneâ¢. We have looked at what is a Composite, seen some of the +Fragments in action, and how simple it is to turn a Composite into a persisted Composite, known as an EntityComposite.</p><p>Next step, <a class="xref" href="thirty-minutes-intro.html" title="Polygene⢠in 30 minutes">Polygene⢠in 30 minutes</a>.</p></div></div><footer xmlns="" xmlns:exsl="http://exslt.org/common" class="footer"><div class="container"><p class="text-muted">Copyright © 2017 The Apache Software Foundation, Licensed under the <a href="http://www.apache.org/licenses/" target="_blank">Apache License, Version 2.0</a>. + Apache Polygene, Polygene, Apache, the Apache feather logo, and the Apache Polygene project logo are + trademarks of The Apache Software Foundation. + All other marks mentioned may be trademarks or registered trademarks of their respective owners. + </p></div></footer><script xmlns="" xmlns:exsl="http://exslt.org/common" src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script><script xmlns="" xmlns:exsl="http://exslt.org/common">window.jQuery || document.write('<script src="js/jquery-1.6.4.min.js"></script>')</script><script xmlns="" xmlns:exsl="http://exslt.org/common" src="https://cdnjs.cloudflare.com/ajax/libs/tether/1.4.0/js/tether.min.js" integrity="sha384-DztdAPBWPRXSA/3eYEEUWrWCy7G5KFbe8fFjk5JAIxUYHKkDx6Qin1DkWx51bBrb" crossorigin="anonymous"></script><script xmlns="" xmlns:exsl="http://exslt.org/common" src="bootstrap-3.3.7/js/bootstrap.min.js"></script><script xmlns="" xmlns:exsl="http://exslt.org/common" src="js/ie10-viewport-bug-workaround.js"></script></body></html> \ No newline at end of file http://git-wip-us.apache.org/repos/asf/polygene-website/blob/bb9c9971/content/java/2017/thirty-minutes-intro.html ---------------------------------------------------------------------- diff --git a/content/java/2017/thirty-minutes-intro.html b/content/java/2017/thirty-minutes-intro.html new file mode 100644 index 0000000..991f017 --- /dev/null +++ b/content/java/2017/thirty-minutes-intro.html @@ -0,0 +1,330 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>Polygene⢠in 30 minutes</title><meta name="generator" content="DocBook XSL Stylesheets V1.78.1" /><link rel="home" href="index.html" title="" /><link rel="up" href="tutorials.html" title="Tutorials" /><link rel="prev" href="ten-minutes-intro.html" title="Polygene⢠in 10 minutes" /><link rel="next" href="howto-depend-on-polygene.html" title="Depend on Polygeneâ¢" /> + + + <meta charset="utf-8"> + <meta http-equiv="X-UA-Compatible" content="IE=edge"> + <meta name="viewport" content="width=device-width, initial-scale=1"> + <!-- The above 3 meta tags *must* come first in the head; any other head content must come *after* these tags --> + <meta name="description" content=""> + <meta name="author" content=""> + <link rel="icon" href="../../favicon.ico"> + + <title>Starter Template for Bootstrap</title> + + <!-- Bootstrap core CSS --> + <link href="bootstrap-3.3.7/css/bootstrap.min.css" rel="stylesheet"> + + <!-- IE10 viewport hack for Surface/desktop Windows 8 bug --> + <link href="css/ie10-viewport-bug-workaround.css" rel="stylesheet"> + + <!-- Custom styles for this template --> + <link href="css/polygene-ng.css" rel="stylesheet"> + + <!-- Just for debugging purposes. Don't actually copy these 2 lines! --> + <!--[if lt IE 9]><script src="../../assets/js/ie8-responsive-file-warning.js"></script><![endif]--> + <script src="js/ie-emulation-modes-warning.js"></script> + + <!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries --> + <!--[if lt IE 9]> + <script src="https://oss.maxcdn.com/html5shiv/3.7.3/html5shiv.min.js"></script> + <script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script> + <![endif]--> + +<!-- favicon --> + +<link rel="shortcut icon" href="http://polygene.apache.org/favicon.ico" type="image/vnd.microsoft.icon" /> +<link rel="icon" href="http://polygene.apache.org/favicon.ico" type="image/x-icon" /> + +<!-- style --> + +<link href="css/shCore.css" rel="stylesheet" type="text/css" /> +<link href="css/shCoreEclipse.css" rel="stylesheet" type="text/css" /> +<link href="css/shThemeEclipse.css" rel="stylesheet" type="text/css" /> +<!--<link href="css/polygene.css" rel="stylesheet" type="text/css" />--> + +<!-- Syntax Highlighter --> + +<script type="text/javascript" src="js/shCore.js"></script> +<script type="text/javascript" src="js/shBrushJava.js"></script> +<script type="text/javascript" src="js/shBrushScala.js"></script> +<script type="text/javascript" src="js/shBrushJScript.js"></script> +<script type="text/javascript" src="js/shBrushBash.js"></script> +<script type="text/javascript" src="js/shBrushPlain.js"></script> +<script type="text/javascript" src="js/shBrushXml.js"></script> +<script type="text/javascript" src="js/shBrushGroovy.js"></script> +<script type="text/javascript" src="js/shBrushPython.js"></script> +<script type="text/javascript" src="js/shBrushRuby.js"></script> +<script type="text/javascript" src="js/shBrushCSharp.js"></script> + +<script type="text/javascript"> + SyntaxHighlighter.defaults['tab-size'] = 4; + SyntaxHighlighter.defaults['gutter'] = false; + SyntaxHighlighter.defaults['toolbar'] = false; + SyntaxHighlighter.all() +</script> + +<!-- JQuery --> + +<script type="text/javascript" src="js/jquery-1.6.4.min.js"></script> + +<!-- Image Scaler --> + +<script type="text/javascript" src="js/imagescaler.js"></script> + +<!-- Table Styler --> + +<script type="text/javascript" src="js/tablestyler.js"></script> + +<!-- Apache Polygene WebSite Progressive Enhancement --> + +<link href="css/progressive-enhancement.css" rel="stylesheet" type="text/css" /> +<script type="text/javascript" src="js/jquery.scrollTo-1.4.2.js"></script> +<script type="text/javascript" src="js/progressive-enhancement.js"></script> + +<!-- Analytics --> + <script type="text/javascript"> + var _gaq = _gaq || []; + _gaq.push(['_setAccount', 'UA-62007352-1']); + _gaq.push(['_trackPageview']); + + (function() { + var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true; + ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js'; + var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s); + })(); + </script> + + </head><body><div xmlns="" xmlns:exsl="http://exslt.org/common" class="logo"><a href="index.html"><img src="images/logo-standard.png" /></a></div><nav xmlns="" xmlns:exsl="http://exslt.org/common" class="navbar navbar-inverse navbar-fixed-top"><div class="container"><div class="navbar-header"><a class="navbar-brand" href="#">Apache<br />Polygene + </a></div><div id="navbar" class="collapse navbar-collapse"><span class="nav navbar-nav"><div xmlns="http://www.w3.org/1999/xhtml" class="toc"><dl class="toc"><dt><span class="section"><a href="index.html#home">Polygeneâ¢</a></span></dt><dt><span class="section"><a href="intro.html">Introduction</a></span></dt><dt><span class="section"><span xmlns="" href="tutorials.html">Tutorials</span></span></dt><dt><span class="section"><a href="javadocs.html">Javadoc</a></span></dt><dt><span class="section"><a href="samples.html">Samples</a></span></dt><dt><span class="section"><a href="core.html">Core</a></span></dt><dt><span class="section"><a href="libraries.html">Libraries</a></span></dt><dt><span class="section"><a href="extensions.html">Extensions</a></span></dt><dt><span class="section"><a href="tools.html">Tools</a></span></dt><dt><span class="section"><a href="glossary.html">Glossary </a></span></dt></dl></div></span></div></div></nav><div xmlns="" xmlns:exsl="http://exslt .org/common" class="sidenav"><div xmlns="http://www.w3.org/1999/xhtml" class="toc"><dl class="toc"><dt><span class="section"><a href="tutorials.html#_overview">Overview</a></span></dt><dt><span class="section"><a href="two-minutes-intro.html">Polygene⢠in 2 minutes</a></span></dt><dt><span class="section"><a href="ten-minutes-intro.html">Polygene⢠in 10 minutes</a></span></dt><dt><span class="section"><span xmlns="" href="thirty-minutes-intro.html">Polygene⢠in 30 minutes</span></span></dt><dt><span class="section"><a href="howto-depend-on-polygene.html">Depend on Polygeneâ¢</a></span></dt><dt><span class="section"><a href="howto-assemble-application.html">Assemble an Application</a></span></dt><dt><span class="section"><a href="tut-composites.html">Transient Composites Tutorial</a></span></dt><dt><span class="section"><a href="tut-services.html">Services Composites Tutorial</a></span></dt><dt><span class="section"><a href="howto-contextual-fragments.html">Use contextual frag ments</a></span></dt><dt><span class="section"><a href="howto-leverage-properties.html">Leverage Properties</a></span></dt><dt><span class="section"><a href="howto-create-constraint.html">Create a Constraint</a></span></dt><dt><span class="section"><a href="howto-create-concern.html">Create a Concern</a></span></dt><dt><span class="section"><a href="howto-create-sideeffect.html">Create a SideEffect</a></span></dt><dt><span class="section"><a href="howto-create-entity.html">Create an Entity</a></span></dt><dt><span class="section"><a href="howto-configure-service.html">Configure a Service</a></span></dt><dt><span class="section"><a href="howto-invocation-annotation.html">Use @Invocation</a></span></dt><dt><span class="section"><a href="build-system.html">Polygene⢠Build System</a></span></dt><dt><span class="section"><a href="community-docs.html">Polygene⢠Documentation</a></span></dt><dt><span class="section"><a href="releasing-apache.html">Releasing Polygeneâ¢</a></span></dt>< /dl></div></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a id="thirty-minutes-intro"></a>Polygene⢠in 30 minutes</h3></div></div></div><div class="tip" style="margin-left: 0.5in; margin-right: 0.5in;"><h3 class="title">Tip</h3><p>Theses tutorials are based on actual code found in the <code class="literal">tutorials/</code> directory of the +<a class="ulink" href="https://polygene.apache.org/download.html" target="_top">Polygene⢠SDK sources</a>. You should start your favorite editor and find the code related to +this tutorial, run it and play with it.</p></div><p>This introduction will deepen your understanding of Polygeneâ¢, as we touches on a couple of the common features of Polygeneâ¢. It +is expected that you have gone through and understood the "Polygene⢠in 10 minutes" introduction.</p><p>If you want to reproduce whatâs explained in this tutorial, remember to depend on the Core Runtime artifact that depends +on Core API, Core SPI, and Core Bootstrap:</p><div class="table"><a id="idm801"></a><p class="title"><strong>Table 3. Artifact</strong></p><div class="table-contents"><table summary="Artifact" border="1"><colgroup><col class="col_1" /><col class="col_2" /><col class="col_3" /></colgroup><thead><tr><th align="left" valign="top">Group ID</th><th align="left" valign="top">Artifact ID</th><th align="left" valign="top">Version</th></tr></thead><tbody><tr><td align="left" valign="top"><p>org.apache.polygene.core</p></td><td align="left" valign="top"><p>org.apache.polygene.core.runtime</p></td><td align="left" valign="top"><p>0</p></td></tr></tbody></table></div></div><br class="table-break" /><p>Moreover, youâll need an EntityStore for persistence and an Indexing engine for querying. Choose among the available +implementations listed in the <a class="xref" href="extensions.html" title="Extensions">Extensions</a> section.</p><p>See the <a class="xref" href="howto-depend-on-polygene.html" title="Depend on Polygeneâ¢">Depend on Polygeneâ¢</a> tutorial for details.</p><p>We will go back to the OrderEntity example;</p><pre class="programlisting brush: java">@Concerns( { PurchaseLimitConcern.class, InventoryConcern.class } ) +public interface OrderEntity + extends Order, Confirmable, + HasSequenceNumber, HasCustomer, HasLineItems, + EntityComposite +{ +} +</pre><p>Letâs say that this is an existing Composite, perhaps found in a library or used in a previous object, but we want to +add that it tracks all the changes to the order and the confirmation of such order.</p><p>First we need to create (or also find in a library) the mechanics of the audit trail. It could be something like this;</p><pre class="programlisting brush: java">public interface HasAuditTrail<M> +{ + AuditTrail<M> auditTrail(); +} + +public interface AuditTrail<M> extends Property<List<Action<M>>> +{} + +public interface Action<T> extends ValueComposite // [2][3] +{ + enum Type { added, removed, completed }; + + @Optional Property<T> item(); // [1] + + Property<Type> action(); // [1] +} + +public interface Trailable<M> +{ + void itemAdded( M item ); + void itemRemoved( M item ); + void completed(); +} + +public class TrailableMixin<M> + implements Trailable<M> +{ + private @This HasAuditTrail<M> hasTrail; + + @Override + public void itemAdded( M item ) + { + addAction( item, Action.Type.added ); + } + + @Override + public void itemRemoved( M item ) + { + addAction( item, Action.Type.removed ); + } + + @Override + public void completed() + { + addAction( null, Action.Type.completed ); + } + + private Action<M> addAction( M item, Action.Type type ) + { + ValueBuilder<Action> builder = + valueBuilderFactory.newValueBuilder( Action.class); // [4] + Action<M> prototype = builder.prototypeFor( Action.class ); + prototype.item().set( item ); + prototype.action().set( type ); + Action instance = builder.newInstance(); + hasTrail.auditTrail().get().add( instance ); + return instance; + } +} +</pre><p>Quite a lot of Polygene⢠features are leveraged above; +[1] Property is a first class citizen in Polygeneâ¢, instead of getters/setters naming convention to declare properties. +[2] ValueComposite for Action means that it is among other things Immutable. +[3] The Action extends a Property. We call that Property subtyping and highly recommended. +[4] The CompositeBuilder creates Immutable Action instances.</p><p>We also need a Concern to hang into the methods of the Order interface.</p><pre class="programlisting brush: java">public abstract class OrderAuditTrailConcern + extends ConcernOf<Order> + implements Order +{ + @This Trailable<LineItem> trail; + + @Override + public void addLineItem( LineItem item ) + { + next.addLineItem( item ); + trail.itemAdded( item ); + } + + @Override + public void removeLineItem( LineItem item ) + { + next.removeLineItem( item ); + trail.itemRemoved( item ); + } + + @Override + public void completed() + { + next.completed(); + trail.completed(); + } +} +</pre><p>In this case, we have chosen to make an Order specific Concern for the more generic AuditTrail subsystem, and would +belong in the client (Order) code and not with the library (AuditTrail). +Pay attention to the @This annotation for a type that is not present in the Composite type interface. This is called a +private Mixin, meaning the Mixin is only reachable from Fragments within the same Composite instance.</p><p>But the AuditTrail subsystem could provide a Generic Concern, that operates on a naming pattern (for instance). In this +case, we would move the coding of the concern from the application developer to the library developer, again increasing +the re-use value. It could look like this;</p><pre class="programlisting brush: java">public class AuditTrailConcern + extends ConcernOf<InvocationHandler> + implements InvocationHandler +{ + @This Trailable trail; + + @Override + public Object invoke( Object proxy, Method m, Object[] args ) + throws Throwable + { + Object retValue = next.invoke(proxy, m, args); + String methodName = m.getName(); + if( methodName.startsWith( "add" ) ) + { + trail.itemAdded( args[0] ); + } + else if( methodName.startsWith( "remove" ) ) + { + trail.itemRemoved( args[0] ); + } + else if( methodName.startsWith( "complete" ) || + methodName.startsWith( "commit" ) ) + { + trail.completed(); + } + + return retValue; + } +} +</pre><p>The above construct is called a Generic Concern, since it implements java.lang.reflect.InvocationHandler instead of the +interface of the domain model. The ConcernOf baseclass will also need to be of InvocationHandler type, and the +Polygene⢠Runtime will handle the chaining between domain model style and this generic style of interceptor call chain.</p><p>Finally, we need to declare the Concern in the OrderEntity;</p><pre class="programlisting brush: java">@Concerns({ + AuditTrailConcern.class, + PurchaseLimitConcern.class, + InventoryConcern.class +}) + +@Mixins( TrailableMixin.class ) +public interface OrderEntity + extends Order, Confirmable, + HasSequenceNumber, HasCustomer, HasLineItems, + EntityComposite +{ +} +</pre><p>We also place it first, so that the AuditTrailConcern will be the first Concern in the interceptor chain +(a.k.a InvocationStack), so that in case any of the other Concerns throws an Exception, the AuditTrail is not updated +(In fact, the AuditTrail should perhaps be a SideEffect rather than a Concern. It is largely depending on how we define +SideEffect, since the side effect in this case is within the composite instance it is a border case.).</p><p>So letâs move on to something more complicated. As we have mentioned, EntityComposite is automatically persisted to an +underlying store (provided the Runtime is setup with one at bootstrap initialization), but how do I locate an Order?</p><p>Glad you asked. It is done via the Query API. It is important to understand that Indexing and Query are separated from +the persistence concern of storage and retrieval. This enables many performance optimization opportunities as well as a +more flexible Indexing strategy. The other thing to understand is that the Query API is using the domain model, in Java, +and not some String based query language. We have made this choice to ensure refactoring safety. In rare cases, the +Query API is not capable enough, in which case Polygene⢠still provides the ability to look up and execute native queries.</p><p>Letâs say that we want to find a particular Order from its SequenceNumber.</p><pre class="programlisting brush: java">import static org.apache.polygene.api.query.QueryExpressions.eq; +import static org.apache.polygene.api.query.QueryExpressions.gt; +import static org.apache.polygene.api.query.QueryExpressions.templateFor; + +import org.apache.polygene.api.query.QueryBuilder; + + [...snip...] + + @Structure private UnitOfWorkFactory uowFactory; //Injected + [...snip...] + + UnitOfWork uow = uowFactory.currentUnitOfWork(); + QueryBuilder<Order> builder = queryBuilderFactory.newQueryBuilder( Order.class ); + + String orderNumber = "12345"; + HasSequenceNumber template = templateFor( HasSequenceNumber.class ); + builder.where( eq( template.number(), orderNumber ) ); + Query<Order> query = uow.newQuery( builder); + + Iterator<Order> result = query.iterator(); + + if( result.hasNext() ) + { + Order order = result.next(); + } + else + { + // Deal with it wasn't found. + } +</pre><p>The important bits are;</p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"> +The QueryExpressions.templateFor() method is used to define the template used in the query upon execution. In + this case, we choose to template only the HasSequenceNumber, an interface used in OrderEntity, but is not part of + Order (may or may not be a good design choice). +</li><li class="listitem"> +The where() clause, which has a statically imported method eq(), which builds up the expression logic, and will + be translated into the underlying query language upon execution, which happens in the iterator() method. +</li></ul></div><p>Another example,</p><pre class="programlisting brush: java">QueryBuilder<Order> builder = queryBuilderFactory.newQueryBuilder( Order.class ); + +LocalDate last90days = LocalDate.now().minusDays( 90 ); +Order template = templateFor( Order.class ); +builder.where( gt( template.createdDate(), last90days ) ); +Query<Order> query = uow.newQuery(builder); + +for( Order order : query ) +{ + report.addOrderToReport( order ); +} +</pre><p>In the above case, we find the Orders that has been created in the last 90 days, and add them to a report to be +generated. This example assumes that the Order type has a Property<Date> createdDate() method.</p><p>Now, Orders has a relation to the CustomerComposite which is also an Entity. Letâs create a query for all customers +that has made an Order in the last 30 days;</p><pre class="programlisting brush: java">QueryBuilder<HasCustomer> builder = queryBuilderFactory.newQueryBuilder( HasCustomer.class ); + +LocalDate lastMonth = LocalDate.now().minusMonths( 1 ); +Order template1 = templateFor( Order.class ); +builder.where( gt( template1.createdDate(), lastMonth ) ); +Query<HasCustomer> query = uow.newQuery(builder); + +for( HasCustomer hasCustomer : query ) +{ + report.addCustomerToReport( hasCustomer.name().get() ); +} +</pre><p>This covers the most basic Query capabilities and how to use it. For Querying to work, an Indexing subsystem must be +assembled during bootstrap. At the time of this writing, only an RDF indexing subsystem exist, and is added most easily +by assembly.addAssembler( new RdfNativeSesameStoreAssembler() ).</p><p>It can be a bit confusing to see Polygene⢠use Java itself as a Query language, but since we have practically killed the +classes and only operate with interfaces, it is possible to do a lot of seemingly magic stuff. Just keep in mind that +it is pure Java, albeit heavy use of dynamic proxies to capture the intent of the query.</p><div class="section"><div class="titlepage"><div><div><h4 class="title"><a id="_conclusion_2"></a>Conclusion</h4></div></div></div><p>We have now explored a couple more intricate features of Polygeneâ¢, hopefully without being overwhelmed with details on how +to create applications from scratch, how to structure applications, and how the entire Polygene⢠Extension system works. +We have looked at how to add a Concern that uses a private Mixin, we have touched a bit on Generic Concerns, and +finally a short introduction to the Query API.</p></div></div><footer xmlns="" xmlns:exsl="http://exslt.org/common" class="footer"><div class="container"><p class="text-muted">Copyright © 2017 The Apache Software Foundation, Licensed under the <a href="http://www.apache.org/licenses/" target="_blank">Apache License, Version 2.0</a>. + Apache Polygene, Polygene, Apache, the Apache feather logo, and the Apache Polygene project logo are + trademarks of The Apache Software Foundation. + All other marks mentioned may be trademarks or registered trademarks of their respective owners. + </p></div></footer><script xmlns="" xmlns:exsl="http://exslt.org/common" src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script><script xmlns="" xmlns:exsl="http://exslt.org/common">window.jQuery || document.write('<script src="js/jquery-1.6.4.min.js"></script>')</script><script xmlns="" xmlns:exsl="http://exslt.org/common" src="https://cdnjs.cloudflare.com/ajax/libs/tether/1.4.0/js/tether.min.js" integrity="sha384-DztdAPBWPRXSA/3eYEEUWrWCy7G5KFbe8fFjk5JAIxUYHKkDx6Qin1DkWx51bBrb" crossorigin="anonymous"></script><script xmlns="" xmlns:exsl="http://exslt.org/common" src="bootstrap-3.3.7/js/bootstrap.min.js"></script><script xmlns="" xmlns:exsl="http://exslt.org/common" src="js/ie10-viewport-bug-workaround.js"></script></body></html> \ No newline at end of file http://git-wip-us.apache.org/repos/asf/polygene-website/blob/bb9c9971/content/java/2017/tools-shell.html ---------------------------------------------------------------------- diff --git a/content/java/2017/tools-shell.html b/content/java/2017/tools-shell.html new file mode 100644 index 0000000..c6c2db1 --- /dev/null +++ b/content/java/2017/tools-shell.html @@ -0,0 +1,333 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>Polygene Generator</title><meta name="generator" content="DocBook XSL Stylesheets V1.78.1" /><link rel="home" href="index.html" title="" /><link rel="up" href="intro.html" title="Introduction" /><link rel="prev" href="intro.html" title="Introduction" /><link rel="next" href="introduction-background.html" title="Background" /> + + + <meta charset="utf-8"> + <meta http-equiv="X-UA-Compatible" content="IE=edge"> + <meta name="viewport" content="width=device-width, initial-scale=1"> + <!-- The above 3 meta tags *must* come first in the head; any other head content must come *after* these tags --> + <meta name="description" content=""> + <meta name="author" content=""> + <link rel="icon" href="../../favicon.ico"> + + <title>Starter Template for Bootstrap</title> + + <!-- Bootstrap core CSS --> + <link href="bootstrap-3.3.7/css/bootstrap.min.css" rel="stylesheet"> + + <!-- IE10 viewport hack for Surface/desktop Windows 8 bug --> + <link href="css/ie10-viewport-bug-workaround.css" rel="stylesheet"> + + <!-- Custom styles for this template --> + <link href="css/polygene-ng.css" rel="stylesheet"> + + <!-- Just for debugging purposes. Don't actually copy these 2 lines! --> + <!--[if lt IE 9]><script src="../../assets/js/ie8-responsive-file-warning.js"></script><![endif]--> + <script src="js/ie-emulation-modes-warning.js"></script> + + <!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries --> + <!--[if lt IE 9]> + <script src="https://oss.maxcdn.com/html5shiv/3.7.3/html5shiv.min.js"></script> + <script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script> + <![endif]--> + +<!-- favicon --> + +<link rel="shortcut icon" href="http://polygene.apache.org/favicon.ico" type="image/vnd.microsoft.icon" /> +<link rel="icon" href="http://polygene.apache.org/favicon.ico" type="image/x-icon" /> + +<!-- style --> + +<link href="css/shCore.css" rel="stylesheet" type="text/css" /> +<link href="css/shCoreEclipse.css" rel="stylesheet" type="text/css" /> +<link href="css/shThemeEclipse.css" rel="stylesheet" type="text/css" /> +<!--<link href="css/polygene.css" rel="stylesheet" type="text/css" />--> + +<!-- Syntax Highlighter --> + +<script type="text/javascript" src="js/shCore.js"></script> +<script type="text/javascript" src="js/shBrushJava.js"></script> +<script type="text/javascript" src="js/shBrushScala.js"></script> +<script type="text/javascript" src="js/shBrushJScript.js"></script> +<script type="text/javascript" src="js/shBrushBash.js"></script> +<script type="text/javascript" src="js/shBrushPlain.js"></script> +<script type="text/javascript" src="js/shBrushXml.js"></script> +<script type="text/javascript" src="js/shBrushGroovy.js"></script> +<script type="text/javascript" src="js/shBrushPython.js"></script> +<script type="text/javascript" src="js/shBrushRuby.js"></script> +<script type="text/javascript" src="js/shBrushCSharp.js"></script> + +<script type="text/javascript"> + SyntaxHighlighter.defaults['tab-size'] = 4; + SyntaxHighlighter.defaults['gutter'] = false; + SyntaxHighlighter.defaults['toolbar'] = false; + SyntaxHighlighter.all() +</script> + +<!-- JQuery --> + +<script type="text/javascript" src="js/jquery-1.6.4.min.js"></script> + +<!-- Image Scaler --> + +<script type="text/javascript" src="js/imagescaler.js"></script> + +<!-- Table Styler --> + +<script type="text/javascript" src="js/tablestyler.js"></script> + +<!-- Apache Polygene WebSite Progressive Enhancement --> + +<link href="css/progressive-enhancement.css" rel="stylesheet" type="text/css" /> +<script type="text/javascript" src="js/jquery.scrollTo-1.4.2.js"></script> +<script type="text/javascript" src="js/progressive-enhancement.js"></script> + +<!-- Analytics --> + <script type="text/javascript"> + var _gaq = _gaq || []; + _gaq.push(['_setAccount', 'UA-62007352-1']); + _gaq.push(['_trackPageview']); + + (function() { + var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true; + ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js'; + var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s); + })(); + </script> + + </head><body><div xmlns="" xmlns:exsl="http://exslt.org/common" class="logo"><a href="index.html"><img src="images/logo-standard.png" /></a></div><nav xmlns="" xmlns:exsl="http://exslt.org/common" class="navbar navbar-inverse navbar-fixed-top"><div class="container"><div class="navbar-header"><a class="navbar-brand" href="#">Apache<br />Polygene + </a></div><div id="navbar" class="collapse navbar-collapse"><span class="nav navbar-nav"><div xmlns="http://www.w3.org/1999/xhtml" class="toc"><dl class="toc"><dt><span class="section"><a href="index.html#home">Polygeneâ¢</a></span></dt><dt><span class="section"><span xmlns="" href="intro.html">Introduction</span></span></dt><dt><span class="section"><a href="tutorials.html">Tutorials</a></span></dt><dt><span class="section"><a href="javadocs.html">Javadoc</a></span></dt><dt><span class="section"><a href="samples.html">Samples</a></span></dt><dt><span class="section"><a href="core.html">Core</a></span></dt><dt><span class="section"><a href="libraries.html">Libraries</a></span></dt><dt><span class="section"><a href="extensions.html">Extensions</a></span></dt><dt><span class="section"><a href="tools.html">Tools</a></span></dt><dt><span class="section"><a href="glossary.html">Glossary </a></span></dt></dl></div></span></div></div></nav><div xmlns="" xmlns:exsl="http://exslt .org/common" class="sidenav"><div xmlns="http://www.w3.org/1999/xhtml" class="toc"><dl class="toc"><dt><span class="section"><a href="intro.html#highlights">Highlights</a></span></dt><dt><span class="section"><span xmlns="" href="tools-shell.html">Polygene Generator</span></span></dt><dt><span class="section"><a href="introduction-background.html">Background</a></span></dt><dt><span class="section"><a href="what-is-cop.html">What is COP?</a></span></dt><dt><span class="section"><a href="what-s-an-object-anyway.html">Whatâs an Object anyway?</a></span></dt><dt><span class="section"><a href="state-modeling.html">Polygene⢠and state modeling</a></span></dt><dt><span class="section"><a href="related.html">Related publications & projects</a></span></dt></dl></div></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a id="tools-shell"></a>Polygene Generator</h3></div></div></div><p>Apache Polygene comes with a Yeoman code generator, to quickly set up a de velopment +environment for Polygene applications.</p><pre class="programlisting brush: shell">mkdir projectdirname +cd projectdirname +yo polygene</pre><p>It will ask a lot of questions. For choice questions, you operate up and down, and with multi-choice, you +select with space bar.</p><div class="section"><div class="titlepage"><div><div><h4 class="title"><a id="_first_trial"></a>First Trial</h4></div></div></div><div class="section"><div class="titlepage"><div><div><h5 class="title"><a id="_project_name"></a>Project Name</h5></div></div></div><p>It starts with the Project name. This will be the project name in Gradle and any gradle driven naming of the +project such as in IDEs. It defaults to current directory with initial uppercase letter.</p><pre class="programlisting brush: shell">? Your project name</pre></div><div class="section"><div class="titlepage"><div><div><h5 class="title"><a id="_java_package_name"></a>Java Package Name</h5></div></div></div><p>This is the root of the package names in the multi-module, multi-package project.</p><pre class="programlisting brush: shell">? Java package name</pre></div><div class="section"><div class="titlepage"><div><div><h5 class="title"><a id="_application_type"></a>Application Type</h5></div></div></div><p>The Application Type that you want to create.</p><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><h3 class="title">Note</h3><p>Command Line is currently not implemented correctly, and the Rest API is still not complete.</p></div><pre class="programlisting brush: shell">? what type of application do you want to create? + Command Line +⯠Rest API</pre></div><div class="section"><div class="titlepage"><div><div><h5 class="title"><a id="_entity_store"></a>Entity Store</h5></div></div></div><p>Polygene has built-in persistence, and that is backed by entity store plugins. There are currently a fair +number of implementations to choose from. Not that "memory" is not persistent, but looses the content on shutdown.</p><pre class="programlisting brush: shell">? Which entity store do you want to use? + Cassandra + File + DerbySQL + Geode + H2SQL + Hazelcast + JClouds + Jdbm + LevelDB +> Memory + MongoDB + MySQL + Preferences + Redis + Riak + PostgreSQL + SQLite</pre></div><div class="section"><div class="titlepage"><div><div><h5 class="title"><a id="_indexin_query_system"></a>Indexin/Query system</h5></div></div></div><p>Select of a pluggable Indexing and Query subsystem.</p><p>In Polygene, the indexing/query system is separated from store and retrieve. This allows us to optimize direct +fetches for navigating object graphs. In practical Polygene applications, we find that querying is not nearly as +common as in, say, JPA applications. The query layout in the underlying indexing system is also very different +from the document-oriented approach of most entity stores.</p><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><h3 class="title">Note</h3><p>Not all indexing subsystems support all of the specified Indexing/Query SPI.</p></div><pre class="programlisting brush: shell">? Which indexing system do you want to use? +> Rdf + ElasticSearch + Solr + SQL</pre></div><div class="section"><div class="titlepage"><div><div><h5 class="title"><a id="_caching_system"></a>Caching System</h5></div></div></div><p>Some of the entity stores rely on a Polygene level caching SPI. This caching subsystem is pluggable and +will be used by any of the entity stores that uses the internal MapEntityStore SPI</p><pre class="programlisting brush: shell">? Which caching system do you want to use? +> None + Memcache + EhCache</pre></div><div class="section"><div class="titlepage"><div><div><h5 class="title"><a id="_serialization_system"></a>Serialization system</h5></div></div></div><p>Serialization is a key concept in business applications, and in Polygene that is a pluggable subsystem.</p><p>? Which serialization system do you want to use?</p><pre class="programlisting brush: shell">> JavaxJson + JavaxXml + MessagePack</pre></div><div class="section"><div class="titlepage"><div><div><h5 class="title"><a id="_metrics_system"></a>Metrics System</h5></div></div></div><p>Metrics is the SPI for measuring the performance and health of an Polygene application. Currently only +one implementation is available.</p><p>? Which metrics capturing system do you want to use?</p><pre class="programlisting brush: shell">> None + Codahale</pre></div><div class="section"><div class="titlepage"><div><div><h5 class="title"><a id="_other_features"></a>Other Features</h5></div></div></div><p>JMX feature installs the MBean server and registers all Services with it, in the application structure defined.</p><p>Mixin Scripting is allowing Mixin methods to be implemented in other languages parallel to Java.</p><p>Security installs Apache Shiro and binds Users, Groups and Roles to entity store.</p><pre class="programlisting brush: shell">? Other features? + ⯠jmx + ⯠mixin scripting + ⯠security</pre></div><div class="section"><div class="titlepage"><div><div><h5 class="title"><a id="_example"></a>Example</h5></div></div></div><pre class="programlisting brush: shell">~/dev/sensetif/sink$ yo polygene +? Your project name Sink +? Java package name com.sensetif.sink +? what type of application do you want to create? Rest API +? Which entity store do you want to use? Cassandra +? Which indexing system do you want to use? Rdf +? Which caching system do you want to use? None +? Which serialization system do you want to use? JavaxJson +? Which metrics capturing system do you want to use? Codahale +? Other features? jmx, security +app name Sink +Entity Stores: Cassandra +Indexing: Rdf +Caching: None +Serialization: JavaxJson +Features: [ 'jmx', 'security' ] + create bootstrap/src/main/java/com/sensetif/sink/bootstrap/config/ConfigurationLayer.java + create bootstrap/src/main/java/com/sensetif/sink/bootstrap/infrastructure/InfrastructureLayer.java + create bootstrap/src/main/java/com/sensetif/sink/bootstrap/domain/DomainLayer.java + create bootstrap/src/main/java/com/sensetif/sink/bootstrap/connectivity/ConnectivityLayer.java + create app/src/main/webapp/WEB-INF/web.xml + create app/build.gradle + create bootstrap/build.gradle + create model/build.gradle + create rest/build.gradle + create build.gradle + create settings.gradle + create gradlew + create gradlew.bat + create gradle/wrapper/gradle-wrapper.jar + create gradle/wrapper/gradle-wrapper.properties + create bootstrap/src/main/java/com/sensetif/sink/bootstrap/config/ConfigModule.java + create bootstrap/src/main/java/com/sensetif/sink/bootstrap/infrastructure/FileConfigurationModule.java + create bootstrap/src/main/java/com/sensetif/sink/bootstrap/infrastructure/RdfIndexingModule.java + create bootstrap/src/main/java/com/sensetif/sink/bootstrap/infrastructure/CodahaleMetricsModule.java + create bootstrap/src/main/java/com/sensetif/sink/bootstrap/infrastructure/JavaxJsonSerializationModule.java + create bootstrap/src/main/java/com/sensetif/sink/bootstrap/infrastructure/CassandraStorageModule.java + create bootstrap/src/main/java/com/sensetif/sink/bootstrap/domain/CrudModule.java + create bootstrap/src/main/java/com/sensetif/sink/bootstrap/domain/JmxModule.java + create bootstrap/src/main/java/com/sensetif/sink/bootstrap/domain/SecurityModule.java + create model/src/main/java/com/sensetif/sink/model/security/CryptoConfiguration.java + create model/src/main/java/com/sensetif/sink/model/security/CryptoException.java + create model/src/main/java/com/sensetif/sink/model/security/CryptoService.java + create model/src/main/java/com/sensetif/sink/model/security/EncryptedStringPropertyConcern.java + create model/src/main/java/com/sensetif/sink/model/security/Group.java + create model/src/main/java/com/sensetif/sink/model/security/RealmService.java + create model/src/main/java/com/sensetif/sink/model/security/SecurityRepository.java + create model/src/main/java/com/sensetif/sink/model/security/User.java + create model/src/main/java/com/sensetif/sink/model/security/UserFactory.java + create bootstrap/src/main/java/com/sensetif/sink/bootstrap/connectivity/RestApiModule.java + create rest/src/main/java/com/sensetif/sink/rest/security/DefaultEnroler.java + create rest/src/main/java/com/sensetif/sink/rest/security/DefaultVerifier.java</pre></div></div><div class="section"><div class="titlepage"><div><div><h4 class="title"><a id="_command_line_options"></a>Command Line Options</h4></div></div></div><pre class="programlisting brush: shell">--import=<modelfile> Imports the model from a JSON file and creates a project descibed therein. +--export=<modelfile> Exports the generated model to a JSON file in the same format as the import model. +--noPrompt If this option is not provided for --import-model, the user can still + input answers, which will override the values in the imported model</pre><div class="section"><div class="titlepage"><div><div><h5 class="title"><a id="_example_2"></a>Example</h5></div></div></div><p>If we run the following,</p><pre class="programlisting brush: shell">$ yo polygene --import=../model.json --noPrompt</pre><p>where the content of the <code class="literal">../model.json</code> is as follows,</p><pre class="programlisting brush: plain">{ + "name": "Sink", + "packageName": "com.sensetif.sink", + "applicationtype": "Rest API", + "features": [ + "security" + ], + "entitystore": "MongoDB", + "indexing": "SQL", + "caching": "Memcache", + "serialization": "JavaxJson", + "metrics": "Codahale", + "modules": { + "user": { + "cruds": [ + { "name": "Users" }, + {"name": "Roles"}, + {"name": "User"}, + {"name": "Role"}, + {"name": "Permission"}, + {"name": "Group"}, + {"name": "Groups"} + ], + "services": [ + { + "name": "AuthService", + "visibility": "application", + "configuration" : [ + { "name": "backend", "type": "java.lang.String" }, + { "name": "connectString", "type": "java.lang.String" } + ] + } + ] + }, + "organization": { + "cruds": [ + {"name": "Organizations"}, + { + "name": "Organization", + "properties": [ + { "name": "name", "type": "java.lang.String" }, + { "name": "created", "type": "java.time.Instant" } + ] + }, + { "name": "Project" } + ], + "entities": [ + { "name": "Invoice" } + ], + "values": [ + { + "name": "CreditLimit", + "properties" : [ + { "name" : "amount", "type" : "java.math.BigDecimal" }, + { "name" : "currency", "type" : "java.lang.String" } + ] + } + ], + "transients": [ + { "name": "OrderConfirmation" } + ], + "objects": [ + { "name": "PaypalNotification" } + ] + }, + "sensor": { + "cruds": [ + { "name": "SensorData" } + ], + "entities": [ + { "name": "Sensor" }, + { "name": "PollSchedule" } + ] + } + } +}</pre><p>we will create a complete project, like this</p><pre class="programlisting brush: shell"> create bootstrap/src/main/java/com/sensetif/sink/bootstrap/config/ConfigurationLayer.java + create bootstrap/src/main/java/com/sensetif/sink/bootstrap/infrastructure/InfrastructureLayer.java + create bootstrap/src/main/java/com/sensetif/sink/bootstrap/domain/DomainLayer.java + create bootstrap/src/main/java/com/sensetif/sink/bootstrap/connectivity/ConnectivityLayer.java + create app/src/main/webapp/WEB-INF/web.xml + create app/build.gradle + create bootstrap/build.gradle + create model/build.gradle + create rest/build.gradle + create build.gradle + create settings.gradle + create gradlew + create gradlew.bat + create gradle/wrapper/gradle-wrapper.jar + create gradle/wrapper/gradle-wrapper.properties + create bootstrap/src/main/java/com/sensetif/sink/bootstrap/config/ConfigModule.java + create bootstrap/src/main/java/com/sensetif/sink/bootstrap/infrastructure/MemcacheCachingModule.java + create bootstrap/src/main/java/com/sensetif/sink/bootstrap/infrastructure/FileConfigurationModule.java + create bootstrap/src/main/java/com/sensetif/sink/bootstrap/infrastructure/SQLIndexingModule.java + create bootstrap/src/main/java/com/sensetif/sink/bootstrap/infrastructure/CodahaleMetricsModule.java + create bootstrap/src/main/java/com/sensetif/sink/bootstrap/infrastructure/JavaxJsonSerializationModule.java + create bootstrap/src/main/java/com/sensetif/sink/bootstrap/infrastructure/CassandraStorageModule.java + create bootstrap/src/main/java/com/sensetif/sink/bootstrap/domain/CrudModule.java + create bootstrap/src/main/java/com/sensetif/sink/bootstrap/domain/UserModule.java + create model/src/main/java/com/sensetif/sink/model/user/Users.java + create model/src/main/java/com/sensetif/sink/model/user/Roles.java + create model/src/main/java/com/sensetif/sink/model/user/User.java + create model/src/main/java/com/sensetif/sink/model/user/Role.java + create model/src/main/java/com/sensetif/sink/model/user/Permission.java + create model/src/main/java/com/sensetif/sink/model/user/Group.java + create model/src/main/java/com/sensetif/sink/model/user/Groups.java + create model/src/main/java/com/sensetif/sink/model/user/AuthService.java + create model/src/main/java/com/sensetif/sink/model/user/AuthConfiguration.java + create model/src/main/resources/com/sensetif/sink/model/user/AuthConfiguration.yaml + create bootstrap/src/main/java/com/sensetif/sink/bootstrap/domain/OrganizationModule.java + create model/src/main/java/com/sensetif/sink/model/organization/Organizations.java + create model/src/main/java/com/sensetif/sink/model/organization/Organization.java + create model/src/main/java/com/sensetif/sink/model/organization/Project.java + create model/src/main/java/com/sensetif/sink/model/organization/Invoice.java + create model/src/main/java/com/sensetif/sink/model/organization/CreditLimit.java + create model/src/main/java/com/sensetif/sink/model/organization/OrderConfirmation.java + create model/src/main/java/com/sensetif/sink/model/organization/PaypalNotification.java + create bootstrap/src/main/java/com/sensetif/sink/bootstrap/domain/SensorModule.java + create model/src/main/java/com/sensetif/sink/model/sensor/SensorData.java + create model/src/main/java/com/sensetif/sink/model/sensor/Sensor.java + create model/src/main/java/com/sensetif/sink/model/sensor/PollSchedule.java + create bootstrap/src/main/java/com/sensetif/sink/bootstrap/domain/SecurityModule.java + create model/src/main/java/com/sensetif/sink/model/security/CryptoConfiguration.java + create model/src/main/java/com/sensetif/sink/model/security/CryptoException.java + create model/src/main/java/com/sensetif/sink/model/security/CryptoService.java + create model/src/main/java/com/sensetif/sink/model/security/EncryptedStringPropertyConcern.java + create model/src/main/java/com/sensetif/sink/model/security/Group.java + create model/src/main/java/com/sensetif/sink/model/security/RealmService.java + create model/src/main/java/com/sensetif/sink/model/security/SecurityRepository.java + create model/src/main/java/com/sensetif/sink/model/security/User.java + create model/src/main/java/com/sensetif/sink/model/security/UserFactory.java + create bootstrap/src/main/java/com/sensetif/sink/bootstrap/connectivity/RestApiModule.java + create rest/src/main/java/com/sensetif/sink/rest/security/DefaultEnroler.java + create rest/src/main/java/com/sensetif/sink/rest/security/DefaultVerifier.java</pre></div></div></div><footer xmlns="" xmlns:exsl="http://exslt.org/common" class="footer"><div class="container"><p class="text-muted">Copyright © 2017 The Apache Software Foundation, Licensed under the <a href="http://www.apache.org/licenses/" target="_blank">Apache License, Version 2.0</a>. + Apache Polygene, Polygene, Apache, the Apache feather logo, and the Apache Polygene project logo are + trademarks of The Apache Software Foundation. + All other marks mentioned may be trademarks or registered trademarks of their respective owners. + </p></div></footer><script xmlns="" xmlns:exsl="http://exslt.org/common" src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script><script xmlns="" xmlns:exsl="http://exslt.org/common">window.jQuery || document.write('<script src="js/jquery-1.6.4.min.js"></script>')</script><script xmlns="" xmlns:exsl="http://exslt.org/common" src="https://cdnjs.cloudflare.com/ajax/libs/tether/1.4.0/js/tether.min.js" integrity="sha384-DztdAPBWPRXSA/3eYEEUWrWCy7G5KFbe8fFjk5JAIxUYHKkDx6Qin1DkWx51bBrb" crossorigin="anonymous"></script><script xmlns="" xmlns:exsl="http://exslt.org/common" src="bootstrap-3.3.7/js/bootstrap.min.js"></script><script xmlns="" xmlns:exsl="http://exslt.org/common" src="js/ie10-viewport-bug-workaround.js"></script></body></html> \ No newline at end of file
