After talking with some people at the DevCon in London and after looking at Records Management source code I noticed that there's actually no good example of how to implement custom documents lifecycle.
I know there's examples of rules and content modeling and even workflows but that solutions can't be really used to implement something more serious like Records Management.
What I'm wondering is how to effectively map a Java solution (I have more experience with OO and Java than Alfresco) to Alfresco. What should be defined as Java class and what should be type/aspect in content model. When to favor behaviour over rules and when to actually use workflows. In my first few projects I used workflows to implement document lifecycle, I wrote quite a lot of bussines/domain logic in workflow nodes - as actions (JS). I found out later that this is quite hard to maintain since you have some code in workflows, some in repository as scripts (Data Dictionary/Scripts) some Java, ...
Is the Records Management good example to start learning from and see some best practices in implementing full document lifecycle? Are there any other resources?
I'm strugling the most with how to implement full lifecycle in java and how to "centralize" the bussines/domain logic.
The scope of ECM is huge, and therefore it's quite hard to come up with completely general guidelines: you really need to stick with the use case you have to address and find the best solution to it. RM is a great example of how to implement a records management solution on top of Alfresco, but it's absolutely useless when it comes to implementing a web publishing process, for which the WCM QS is what you want to look at as a starting point.
On the whole of APIs Alfresco offers to developers, their inner characteristics are ultimately the best resource to understand when to use them. Let's see if I can make sense of (at least most important among) them.
Content Types
This is where you always need to start implementing an Alfresco project. You need to closely work with someone with deep domain knowledge of the documental processed you need to implement, and define root elements for different document lifecycles. In Alfresco you must assign one and only one content type to a given node. This is done at content creation time, and it's not often changed along the content lifecycle. Thus, content types are normally used to identify content items with radically different lifecycles (e.g. cm:document and ws:article), and defining a content type means to extract the basic meta data properties that will be used or useful along the whole document lifecycle.
Aspects
While content types are basically a static vertical classification and enrichment of documents, aspects are their dynamic cousins. As opposed to content types, you can apply or remove aspects dynamically with lesser-to-none destructive consequences to the content nodes. They can or not enrich the document with more metadata, and can be applied to items regardless of their content types. These characteristics make aspects possibly the most flexible feature of the Alfresco content model: you can use them to to mark content or enable/disable operations shared among different content lifecycles (e.g. cm:versionable, rma:filePlanComponent). By nature, aspects are meant to handle cross cutting concepts that occur in several distinct lifecycles or lifecycle steps.
Behaviors
Here we start an overview of how to add logic in your Alfresco solution. Behaviors are automatic computations that are fired by specific triggers, where triggers are defined as a [type/aspect, policy] pair (e.g. [cm:versionable, onCreateNode]). They are in general executed within the same transaction of the event that fires the trigger, there's no guarantee on the order of execution and there's no coordination or orchestration. This makes them perfect for automatic content generation or handling (e.g. creating a thumbnail or updating some metadata) which needs to be integral parts of the content lifecycle, but that are not strictly part of a formalized process.
They're rather accessory or supplementary operations for normal operations or workflows. They require Java coding, thus forming a rather fixed part of your solution. You normally identify and design behaviors right after finishing the content modeling phase and before starting designing the workflows.
Rules
Similar to behaviors, rules are triggered upon specific events, but they're a much more generic and dynamic than them. You can configure rules only on folders, at runtime, and bind them to events that happen within the folder. This makes them ideal to create special buckets within your content repository (e.g. send an email whenever content is added to a specific folder), where side effects happen when you deal with content within it. They're implemented as hidden nodes within folders, thus being integral parts of an export: you can in theory borrow them in different Alfresco implementations, provided the required pieces are available.
They normally are used when a piece of logic applies to content of several different types, but possibly not all the items of the affected types, and only when you can store all the affected content nodes within a sub branch of the repository. Even if such constraint might sound heavy, rules turn out to be quite a handy tool (e.g. generate a thumbnail for all the png documents with mime type image/png in /images).
Actions
Actions are bundled pieces of logic that can be invoked against a node on demand. They're the building blocks for rules, and often used within workflows (e.g. send an email). They are also handy to be directly bound to UI components/buttons, in order to allow the user to be directly exposed to available features of your application. You normally end up developing an action when you need (of want to enable) reusing the same piece of logic in different contextes, such as a workflow, a rule and/or direct user interaction.
Workflows
This is probably the core business of document management: workflows allow you to build a coordinated process that guides users through a defined sequence of steps, basically implementing a human algorithm. Workflows allow you to write custom code, but for the sake of maintainability you probably want to limit such code to the bare minimum of what the workflow itself needs in order to execute, and externalize more complex operations to actions or scripts.
If you're doing document management, the design and implementation of a workflow can start right after content modeling, possibly spawning several other development activities such as accessory actions and scripts, and they're likely to last until you call your code feature complete, and you start fiddling with all the infinite change requests or leftovers on the UI :-)
Related
What are the differences of using Spring Data REST repository alone and implementing the “service” pattern around it (that is ItemService, ItemServiceImpl and so on)?
At the first glance the functionality is more or less the same with the difference that the service approach allows for a better customization but it also produces loads of boilerplate code (the implementation and the controller). Here is an example (look Payment and CreditCard entities) of using both approaches - RESTBucks of Oliver Drotbohm.
The payment abstraction there uses the "service" pattern used (PaymentService, PaymentImpl and then PaymentController with all methods in web folder) while the orders are exposed via Spring Data REST directly.
tl;dr
The payment functionality lives at a higher level of abstraction as it doesn't follow established HTTP resource patterns (collection resource, item resource, in general: the ones described here) and thus warrants a custom service implementation. In contrast, the lifecycle of the order aggregate does indeed follow those patterns and thus doesn't need anything but Spring Data REST exposure plus a few customizations. Find a conceptual overview about how the two implementation parts relate to each other here.
Details
That's a great question. The sample application is designed to showcase how different parts of an API can be driven by different requirements and how you can use Spring Data REST to take care of the parts that follow established patterns but at the same time augment it with higher level aspects that are needed to express business processes.
The application is split into two major parts: the order handling that's centered around the Order aggregate that is taken through different stages. A conceptual overview about those can be found here. So parts of our API for the orders will be following standard patterns: filterable collection resources to see all orders, add new orders etc. This is where Spring Data REST shines.
The payment part is different. It somehow needs to blend into both the URI and functional space of the order handling. We achieve that by the following steps:
We implement the required functionality in a dedicated service. The repository interaction doesn't match the necessary level of abstraction as we have to verify business constraints on both the Order and Payment aggregates. That logic needs to live somewhere: in the service.
We expose that functionality via a Spring MVC controller as we (currently) don't need standard patterns like listing all payments. Remember, the example is centered around modeling the ordering process, it's not an accounting backend. The payment resources are blended into the URI space of the orders: /orders/{id}/payment.
We use hypermedia elements to indicate when the functionality can be triggered by adding a link pointing to those resources conditionally so that clients can use the presence or absence of those elements to decide what UI affordances to offer to trigger that functionality.
Here's what I think is nice about this approach:
You only manually code the parts that are important from the business point of view. No need to implement a lot of boilerplate code for the parts of the API that follow well established patterns.
Clients don't need to care where exactly that seam is. Using hypermedia elements, the API just looks like one thing to the client. The server could even move the payment resources to a different URI space or a different service even.
Resources
This deck discusses what I described in detail. Here's a video recording of it. If you're interested in the higher level ideas of especially the drive towards hypermedia, I suggest this slide deck, too
Your service contains all the logic, but the repository layer is as stupid as possible. Its task is a specific operation(for ex. save, edit).
Spring Data is an additional convenient mechanism for interacting with database entities, organizing them in a repository, extracting data, changing it. in some cases, it will be enough to declare the interface and method in it, without implementing it.
P.S
and it's a good choice if you're creating a simple crud
There's plenty of resources that outline how URLs should be organized for RESTful APIs but for web in general there's little to be found.
How can I structure the URLs of the web pages so that they are
Sensible from the perspective of a user browsing the web
Sensible from a separation of concerns in a Spring framework controller
To apply some context let's assume there's groups that contains elements and there are uses cases to create, view, edit and delete both.
You may have had trouble finding information about this since it's a question that touches on Information Architecture (IA) and SEO, in addition to application design. If your application or site is available on the internet (rather than an internal private network) then you have to optimize multiple, sometimes conflicting, constraints:
Making the urls sensible and understandable to users
Make your scheme manageable and scalable
Understand which portions of your app or site need to be indexible by search engines
Maintain good application design (think SOLID)
Probably several others ...
In general, I would suggest that you start with identifying your constraints, and consider "what makes sense to users" as a high priority one. Then try to work in other constraints from there. Since you mention separation of concerns, you have a good sense of what some of your design constraints are. Ultimately, it's up to you (and maybe your business SMEs) to determine which constraints need to be rigid, and which others can be relaxed.
After consideration I've come to think this
/groups/create
/group/{gid}/
/group/{gid}/edit
/group/{gid}/delete
/group/{gid}/elements/create
/group/{gid}/element/{eid}/
/group/{gid}/element/{eid}/edit
/group/{gid}/element/{eid}/delete
The only drawback is that groups are created against /groups/create rather than /group/create because otherwise the group name create would become illegal.
Another variant is to attach the id at the very end, but urls quickly become clumsy
/groups/create
/groups/view/{id}
/groups/edit/{id}
/groups/delete/{id}
/groups/view/{id}/element/create
/groups/view/{id}/element/view/{eid}
/groups/view/{id}/element/edit/{eid}
/groups/view/{id}/element/delete/{eid}
I am attempting a study of JavaFX because I want to use it as the GUI of my program. My question is essentially a conceptual one:
To date my program is mostly the "Model" part of the MVC pattern; that is, almost all of my code is the OO-representation of abstractions in the sense of classes, and all of that code is logical code.
Since I do not want to be the only user of my program, I want to add the "View" part of MVC so that people can easily use and manipulate the "Model" part of my program. For this, I want to use JavaFX.
In my "Model" classes I obviously use various Lists, Maps, and other classes from the Java Collections API. In order to let the users of my program manipulate these underlying Lists and Maps I want to use the Observable(List/Map) interfaces in JavaFX.
A concrete example to bring clarity to the situation:
Let's say that I have a MachineMonitor class that every 3 minutes checks certain properties of a Machine, such as if the connection is still good, the speed that the gears are turning, etc. If certain inequalities are met (say that the speed of the gears has fallen to a rate of 1 turn/sec) the MachineMonitor fires a RestartMachineEvent.
Currently I use an ArrayList<MachineMonitor> to keep track of all of the individual MachineMonitor's. Now extending to the "View" part of MVC, I want the User to be able to manipulate a TableView that displays the list of MachineMonitors so that they can, for instance, create and remove new MachineMonitor's to monitor various Machines.
So that I can keep track of what the user of my program wants to do (say, create a MachineMonitor for Machine #5 that checks to see if the turn/sec of the gears falls below 0.5) I use an ObservableList<MachineMonitor> as the underlying List for the TableView.
The easiest way to link the "Model" and "View" of my program would simply be to change the "Model" class to have an ObservableList<MachineMonitor> and not an ArrayList<MachineMonitor> but (getting to the topic of the question) I feel that this is very messy because it mixes "Model" and "View" code.
A naïve approach would be to use an ObservableList<MachineMonitor> for the TableView and retain the use of my ArrayList<MachineMonitor>. However, changes made to the ObservableList<MachineMonitor> do not affect the underlying List as per the JavaFX specifications.
Given this, is the best way to solve this conundrum to make a ChangeListener for the ObservableList<MachineMonitor> that "propagates" the changes made to the ObservableList<MachineMonitor> to the underlying "Model" ArrayList<MachineMonitor>? Perhaps put this in a class called MachineMonitorController?
This ad-hoc solution seems very messy and non-ideal.
My question is: What is the best way to retain nearly complete separation between the "Model" and "View" in this scenario?
Briefly, I don't think use of ObservableList breaks the MVC contract.
The rest, you may read or not as you wish, as it is quite annoyingly long.
Architectural Pattern Background
Observables are useful in MVC style architectures because they provide a way of feeding data back and forth between the MVC components through loose couplings where the model and view classes don't need to refer directly to each other, but can instead work with some shared data model which communicates data flow. It's not a coincidence that the Observable pattern and the MVC style architecture concept both originated around the same time at Xerox PARC - the things are linked.
As noted in Martin Fowler's GUI architectures, there are numerous different approaches to building GUIs. MVC is just one of these, kind of the granddaddy of them all. It is nice to understand MVC well (it is often misunderstood) and MVC concepts are applicable in many places. For your application you should use the system which feels best for you rather than rigidly following a given pattern (unless you are using a particular framework which enforces a given pattern) and also be open to adopting different patterns within an application rather than trying to shoehorn everything into a single conceptual framework.
Java Beans are a fundamental part of almost all Java programs. Though traditionally often only used in client apps, the observer pattern, through PropertyChangeListeners, has been, for good reason, a part of the Java Bean specification since it was created. The observable and binding elements of JavaFX are a rework of that earlier work, learning from it to build something that is both more convenient to work with and easier to understand. Perhaps, if the JavaFX observable and binding elements had existed ten or twelve years ago as part of the JDK, such concepts would be more generally used in a wider variety of libraries and frameworks than a couple of pure GUI frameworks.
Advice
I suggest considering the MVVM model and other GUI architectures.
If you want a dead-easy framework which follows a model, view, presenter style, definitely give afterburner.fx a spin.
I think the correct choice of architecture depends on your application, your experience and the size and complexity of the problems you are trying to solve. For instance, if you have a distributed system, then you could follow REST principles rather than (or in addition to) MVC. Whichever you choose, the architecture should aid you in solving the problem at hand (and possibly future problems) and not the converse. Over-architecting a solution is a common trap and is very easy to do, so try to avoid it.
Caveat
One caveat to consider is that observables necessarily work via side-effects which can be difficult to reason about and can be antithetical to the concept of isolation. JavaFX features some good tools, such as ReadOnlyObjectWrapper and ReadOnlyListWrapper, to help limit the impact (damage control if you like) on observables so they don't run amok in your system. Use such tools (and immutable objects) with reckless abandon.
Learn from Examples
For a simple JavaFX application which is built using observables, refer to tic-tac-toe.
For a good way to structure a large and complex JavaFX application with FXML based components, refer to the source code for SceneBuilder and SceneBuilderKit. The source code is available in the JavaFX mercurial source tree, just check it out and start learning.
Read up on the JavaFX UI controls architecture. Examine the JavaFX controls source code (e.g. Button and ButtonSkin or ListView and ListViewSkin) to see how concepts such as MVC can be applied using JavaFX structures. Based on that learning, try creating some of your own custom controls using the architecture that the JavaFX controls framework provides. Often, when you are building your own application you don't need to create your own controls (at least ones which derive form JavaFX Control). The JavaFX Controls architecture is specially crafted to support building libraries of reusable controls, so it is not necessarily generally suitable for all purposes; instead it provides a concrete demonstration of one proven way to get certain things done. Adopting and adapting proven solutions goes a long way to ensuring you don't reinvent stuff needlessly and allows you to build on a solid base and learn from the trials of others.
Regarding your Concrete Example
I advise you to go with:
The easiest way to link the "Model" and "View" of my program would simply be to change the "Model" class to have an ObservableList and not an ArrayList
Maybe use a ReadOnlyListWrapper to expose the ObservableList from the MachineMonitor to the outside world, so that nothing can modify it unduly.
Setup some other structure which encapsulates the view (for example a ControlPanel and ControlPanelSkin) and provide it a reference to the read only observable list of MachineMonitors. The ControlPanelSkin can encapsulate a TableView, a graph or whatever visual knobs and widgets you want to use for the user to monitor the machines.
Using such a structure effectively isolates your view from the model. The model really doesn't know anything about the UI at all and ControlPanelSkin implementation could be changed out to a completely different visual representation or technology without changing the core MachineMonitor system at all.
The above just outlines a general approach, you'll need to tweak it for your specific example.
I disagree that using an ObservableList in your "model" class violates MVC separation. An ObservableList is purely data representation; it is part of the model and not part of the view. I (and others) use JavaFX properties and collections in model representations in all tiers of my applications. Among other things in there, I point out how I use JavaFX properties that are (or can be, at least) bound to JSF. (I should mention that not everyone agrees with the approach of using FX properties on the server side; however I don't really see any way to make the argument that they are somehow part of the view.)
Also, if you do
List<MachineMonitor> myNonObservableList = ... ;
ObservableList<MachineMonitor> myObservableList = FXCollections.observableList(myNonObservableList);
myObservableList.add(new MachineMonitor());
the observable list is backed by the non-observable list, so the change occurs in myNonObservableList too. So you can use this approach if you prefer.
I have a lot of existing data in my database already, and want to develop a points mechanism that computes a score for each user based on what actions they do.
I am implementing this functionality in a pluggable way, so that it is independent of the main logic, and relies on Spring events being sent around, once an entity gets modified.
The problem is what to do with the existing data. I do not want to start collecting points from now, but rather include all the data until now.
What is the most practical way to do this? Should I design my plugins in such a way as to provide for an index() method, which will force my system to fetch every single entity from the database, send an EntityDirtyEvent, to fire the points plugins, for each one, and then update it, to let points get saved next to each entity. That could result in a lot of overhead, right?
The simplest thing would be to create a complex stored procedure, and then make the index() call that stored procedure. That however, seems to me like a bad thing either. Since I will have to write the logic for computing the points in java anyway, why have it once again in SQL? Also, in general I am not a fan of splitting business logic into the different layers.
Has anyone done this before? Please help.
First let's distinguish between the implementation strategy and business rules.
Since you already have the data, consider obtaining results directly from the data. This forms the data domain model. Design the data model to store all your data. Then, create a set of queries, views and stored procedures to access and update the data.
Once you have those views, use a data access library such as Spring JDBC Template to fetch this data and represent them into java objects (lists, maps, persons, point-tables etc).
What you have completed thus far does not change much, irrespective of what happens in the upper layers of the system. This is called Model.
Then, develop a rule base or logic implementation which determines, under what inputs, user actions, data conditions or for all other conditions, what data is needed. In mathetical sense, this is like a matrix. In programming sense, this would be a set of logic statements. If this and this and this is true, then get this data, else get that data, etc. This encompasses the logic in your system. Hence it is called "Controller".
Do not move this logic into the queries/stored procedure/views.
Then finally develop a front-end or "console" for this. In the simplest case, develop a console input system, which takes a .. and displays a set of results. This is your "view" of the system.
You can eventually develop the view into a web application. The above command-line view can still be viable in the form of a Restful API server.
I think there is one problem here to be considered: as I understand there's huge data in the Database so the idea to create only one mechanism to calculate the point system could not be the best approach.
In fact if you don't want to start collecting points but include all the data, you must process and calculate the information you have now. Yes, the first time you will run this can result an overhead, but as you said, you need this data calculated.
By other hand you may include another mechanism that attends changes in an entity and launches a different process capable of calculate the new pointing diffence that applies to this particular modification.
So, you can use one Service responsible of calculate the pointing system, one for a single entity and another, may be longer to finish, capable of calculate the global points. Even, if you don't need to be calculated in real-time you can create a scheduled job responsible of launch it.
Finally, I know it's not a good approach to split the business logic in two layers (Db + Java) but sometimes is a requirement do it, for example, if you need to reply quickly to a request that finally works with a lot of registries. I've found some cases that there's no other option than add business logic to the database (as a stored procedures, etc) to manage a lot of data and return the final result to the browser client (ex: calculation process in one specific time).
You seem to be heading in the right direction. You know you want your "points" thing decoupled from the main application. Since it is implied you are already using hibernate (by the tag!), you can tap into the hibernate event system (see here section 14.2). Depending upon the size/complexity of your system, you can plugin your points calculations here (if it is not a large/complex system), or you can publish your own event to be picked up by whatever software is listening.
The point in either design approach is that neither knows or cares about your point calculations. If you are, as I am guessing, trying to create a fairly general purpose plugin mechanism, then you publish your own events to that system from this tie-in point. Then if you have no plug-ins on a given install/setup, then no one gets/processes the events. If you have multiple plug-ins on another install/setup, then they each can decide what processing they need to do based upon the event received. In the case of the "points plugin" it would calculate it's point value and store it. No stored proc required....
You're trying to accomplish "bootstrapping." The approach you choose should depend on how complicated the point calculations are. If stored procedures or plain update statements are the simplest solution, do that.
If the calculations are complicated, write a batch job that loads your existing data, probably orders it oldest first, and fires the events corresponding to that data as if they've just happened. The code which deals with an event should be exactly the same code that will deal with a future event, so you won't have to write any additional code other than the batch jobs themselves.
Since you're only going to run this thing once, go with the simplest solution, even if it is quick and dirty.
There are two different ways.
One is you already know that - poll the database for for changed data. In that case you are hitting the database when there may not be change and it may slow down your process.
Second approach - Whenever change happens in database, the database will fire the event. That you can to using CDC (Change Data Capture). It will minimize the overhead.
You can look for more options in Spring Integration
Over the past year I have heard alot about Velocity and NVelocity. Reading their documentation and doing searches on the net hasn't given me the answers I was looking for.
In what situation would I use this library in my development? What problem does it solve that didn't already have a solution?
Since the dawn of web apps, people started to think about separation of concerns in many applications, including web applications. The challenge is to separate what is view code from what is business code, or logic code. When jsps first arrived, many people where coding lots of logic in jsps directly (stuff like db access and other), breaking the basic principle of separation of concerns (jsps should be responsible for the presentation, not for the logic).
Velocity, Freemarker and others are templating engines that allows the separation of UI logic and business logic, thus facilitating changes in the presentation while minimizing the changes on the business side. These template engines have facilities for doing common UI tasks such as showing a block of html if some condition holds true, or iterating over a list while maintaining logic code outside of the view. This is fundamental for maintaining a complex application in the long run.
I think it's important to point out that compared to JSP/ASP.NET as a templating mechanisim, Velocity/NVelocity really 'ENFORCE' the seperation of concern.
With <% .. %> of JSP/ASP.NET, any Java/.NET code is allowed. Which is why sometimes you do see business logic code in these files.
With Velocity/NVelocity you can't embed long series of code. Instead you are really forced to pass in computed values, which Velocity/NVelocity picks up and displays them according to the way the template is designed.
Another point would be that they can work outside of a Web Container environment (at least Velocity can AFAIK). Imagine that you had designed a report template with JSP/ASP.NET. It works fine from the web. And then suddenly there is a change request to have it be done from a Desktop application. Rather than embed a Web Container in it, you could initialize Velocity/NVelocity, compute the values, then render the template.
It's a template engine. If you have a lot of static text with variable content mixed in, templates are a great way to reduce the amount of work you have to do.
It's a whole lot better than String.Format or loads of concatenation because it's not as repetitive or error prone, and far more maintainable since you can figure out exactly what your template does just by looking at it.
We use templating to generate configuration files for production, UAT, system test, contingency systems etc.
We have a master Spring configuration file into which we inject a property file. We have a master property file that is parsed by Velocity and this allows us to keep all system settings in one file.
As a bonus, for the ones interested, I recommend reading the following:
http://www.artima.com/lejava/articles/stringtemplate.html
http://www.cs.usfca.edu/~parrt/papers/ST.pdf
These are links about StringTemplate, a templating engine by Terence Parr who wrote antlr, a parser that's been used everywhere (ex: hibernate uses antlr).
1 - Velocity engine actually merges the real time data with the xyz.vm file which holds the static information 2 - The vm file uses Velocity Template Language(VTL)
(It can iterate over the java iterable java objects placed on the context , can call the methods accessible by the objects placed on the context) Situations to use Velocity - Brings the power of java to html not only to html 1-When you have to generate report mails often with varying data and constant style.(foreach support)
2-When you want to merge a real time data with dummy place-Holder in deeply nested contents
3-When you want to decide style information based on the value of the data (if else support)and many more
Refer - http://velocity.apache.org/engine/releases/velocity-1.5/user-guide.html