Assemblies
See the Glossary for definitions of terms used here.
Assembly Details
When you install an assembly containing applications into a home directory,
the app automatically is accessible via the home name plus the application
name within the assembly. Mappings are searched first, then direct
searching is tried, if it is turned on. If you do not map
a URI to the app, the URI would be
/{homedir-name}/{assembly-name}/apps/{appname}
unless you turn off direct searching of applications. For a production
server, you would want direct searching turned off, and only allow applications
that were explicitly mapped in the web-apps file to be accessed. Note
that none of these scenarios result in files being directly accessible
via the URL. These just define search locations for the Application
to find its base directory. The Application still uses a ResourceManager
to load all files.
(Map URI's to apps within assemblies)
web-apps.xml |
/demo
|
/homes/acme/com-acme-apps-7/apps/demo
|
/catalog
|
/homes/acme/com-acme-apps-7/apps/catalog
|
/dynamide/ide
|
/homes/dynamide/com-dynamide-apps-60/apps/ide
|
|
The above mapping behaves differently in Self-Hosted Mode and Hosted Mode:
- In Self-Hosted Mode: http://www.acme.com/demo
- In Hosted Mode: http://apps.dynamide.com/acme/demo
Without the mapping, the following default URL obtains:
- Self-Hosted Mode: http://www.acme.com/acme/com-acme-apps-7/apps/demo
- Hosted Mode: http://apps.dynamide.com/acme/com-acme-apps-7/apps/demo
Of course, in Self-Hosted Mode, you can name the accounts anything, such
as /dev, /qa, and so on.
For example
- http://www.acme.com/qa/com-acme-apps-7/apps/demo
The com-dynamide-apps assembly contains the following assembly.xml
file:
assembly.xml |
basename
|
com-dynamide-apps
|
interface
|
1
|
build
|
59
|
imports
|
com-dynamide-lib,1,59+
|
|
...
|
monitor
|
com.dynamide.AssemblyMonitor
|
|
To save some implementation time, and some
figuring out of fancy parsing, just implement the version sequences as
child elements:
<imports>
<import>
<basename>com-dynamide-lib</basename>
<interface>
<version>1</version>
</interface>
<builds>
<version>1</version>
<version>3</version>
<version>*</version>
<version>5</version>
<version>7</version>
<version>*</version>
</builds>
</import>
<imports>
Implies builds versions 1, 3-5, 7+
The default for builds is *.
It is questionable whether to allow interface numbers to use open-ended
ranges. And open ended build ranges may also be lax. If you allow
them, make a utility that reports on all apps that are running with
future versions of imports. It should also show you which apps need
to be tested because new interfaces are available. It should then
let you upgrade to the new interface.
Note that the assembly has a basename and a build number. These
two items determine the globally unique identifier for this assembly.
The interface number is for clients that wish to bind to this library
as long as the interface doesn't change. The interface is the sum
of all Objects and API calls that the interface makes visible (public).
Typically, changing method signatures or removing Objects or API
calls would mandate a new interface number. Dynamide doesn't check
the interface, the library author is responsible for determining if two
versions have the same effective interface, since the interface to a
Dynamide assembly includes widgets, pagetypes, editors, designers, properties,
events, Javascript functions, Java objects, and Java methods, mosts
of which cannot be validated with a compiler.
An import can be based on a basename, an interface version string, and
a build version string. Version strings can be absolute numbers,
ranges, or open-ended ranges. "3" means just version 3, "1-2" means
version 1 through 2, "1+" means all versions later than 1.
An Assembly can contain a web-apps.xml file. This file
can be merged into the master web-apps.xml file. There is no implementation
for this yet, but the rule would be to allow URI's if they don't cause
conflicts.
I think that the web-apps should be an element
inside an assembly.xml file
An Assembly can be zipped up into a zip file, in order to move it to
another host. The Assembly directory name should not be included
in the path of the included files. That is, within the zip file, the
root directory should be the assembly directory. The name of the
zip file will be used to extract it to a directory with that name.
Here's an example:
Directory:
- com-acme-catalog-8/ -- Acme's catalog assembly, build 8
- assembly.xml
- apps/
- app1/
- application.xml
- page1.xml
Zip file:
com.acme-catalog-8.zip
|
Filename
|
Path
|
assembly.xml
|
/
|
application.xml
|
/apps/app1
|
page1.xml
|
/apps/app1
|
app1.css
|
/apps/app1/resources/css
|
|
However, the name that counts is the basename in the assembly.xml file,
together with the interface and build version numbers. To avoid confusion
with Java package names, make the basename using dashes, using
all lower-case letters, and include library name plus the build
number. Use a new, single integer build number for each build or
assembly release, not major-minor-build-bugfix. Bugfixes back in
the realease series would have to have a higher build number for Dynamide
to be able to decide to use it preferentially. If you change the
functionality, consider using a new interface number.
For example, Dynamide distributes com-dynamide-apps-59, which is all
the applications as of build 59. The widgets and other shareable
resources are assembled into com-dynamide-lib-59. The interface
version number is specified in the assembly.xml file, so is not used
in the assembly zip file name. When the assembly is registered,
Dynamide will use the values in the assembly.xml file, not the assembly
zip file or directory name. Those names are just to avoid conflict
with other assemblies installed on the same host.
Applications define imports of Assemblies. Assemblies can
thus import multiple versions of the same Assembly. The search
path is per-Application, not per-Assembly.
Widgets and Applications can require Java interfaces, and assembly interface
numbers. The Application decides which Java interface or assembly
interface version to bind to. The widget declares that it "requires"
a certain interface level. If this level is not available, the
widget refuses to load, and logs an ERROR. This can be captured
with automated testing. Test mode is turned on so that widgets
don't open DB connections, etc., and all pages and all widgets
are loaded and rendered. Errors and Warnings can be inspected. For
a successful test, ERROR count must be zero, and WARNING
count should be zero.
Imports are specified in the Dynamide objects.
An application specifies imports in application.xml:
Here's an example from an application that imports com-dynamide-lib,
interface version 1, and any builds including build 59 or higher. It
also imports com-acme-apps interface version 1, all builds.
<application>
<properties>
<property name='imports'>
<dataType>com.dynamide.datatypes.Enumeration</dataType>
<value>
<enumeration override="true">
<item dataType="com.dynamide.datatypes.Version">
<basename>com-dynamide-lib</basename>
<interface>1</interface>
<build>59+</build>
</item>
<item>
<basename>com-acme-apps</basename>
<interface>1</interface>
<build>1+</build>
</item>
</enumeration>
</value>
<helpTip>items: a list of Strings.</helpTip>
</property>
...
<properties>
...
</application>
Imports affect the search path for resources. Each application
has its own instance of the ResourceManager, which searches for resources.
The ResourceManager has a list of places to search, similar to
a search path in a command shell. The search order is:
- relative to the application directory
- relative to the assembly directory
- relative to the imported assembly directories, in the order that
assemblies are imported
Assemblies may be imported from an account home directory, or from the
shared assembly directory, called $RESOURCE_ROOT/assemblies/.
Finally, Dynamide discovers where the root of the assemblies is and
how to handle virtual server host names by how Resin is configured with
this file:
resin.conf |
names virtual server mappings
names Dynamide Root directory
|
Use Cases
- Add an application
- Hosted Mode:
- In hosted mode, all assemblies live under a home directory
for an account. Each organization and each user has an
account, so /john and /acme would be available if user
"john" signed up as a developer with organization "acme". John
would develop in /john, and push to production in /acme.
- In the hosted version of Dynamide, you can only install
applications in your account directory. This means all
URI's begin with your account name:
- /acme/catalog
- for example:
- http://www.dynamide.com/acme/catalog
- Actions:
- Dynamide will resolve the account name and look in that
account's home directory, and consult the web-apps file there
to find the application.
- Note: within your application code you refer to $application.URI
so that you never have to hardcode the URI.
- Self-Hosted Mode
- You come up with whatever application URI's you want:
- /catalog
- for example:
- http://www.acme.com/catalog
- Developers have accounts on the server. Developers develop
within their home directories, then push to the Q/A or Production
directories. So user "john" develops /john/demo, then pushes
to /demo.
- You can create accounts for roles and groups instead of individuals
if you wish to manage concurrent access issues yourself. For
example, you could have a "qa" account for doing Q/A testing
on the same machine as development, then only allow one administrator
to "push" files into /qa/ at a time. Similarly, you could
define /dev/ if you had one developer creating pages and the
application files in the Dynamide IDE, another developer designing
the XSL files, and another developer in charge of CSS files
and images. Since they all update the /dev/demo application, their
changes are in sync in one sandbox, but you come up with some
communication or responsibility scheme so that files are not
overwritten.
- Action
- Dynamide will consult the global web-apps file to find the
application
- Promote a resources directory to a library using assemblies
- create an assembly directory, mark it with a version and id,
copy the resources directory.
- Create an assembly with multiple applications
- package up the current assembly, with sibling applications that
may or may not have dependencies.
- Create assemblies with independent applications
- split out apps into assemblies, but assumes that apps don't
depend on each other.
- copy apps/{app} directory, including apps/{app}/resources.
- copy /resources directory.
- Share resources between applications
- make a "resources" directory at the assembly level, move resource
from apps/{app}/resources to this new directory.
- Create Monolythic assemblies
- All the files in this assembly, plus any imported assemblies.
- Does not include Java jar files.
- Suitable for installing on a Dynamide server that has all the
correct Java jar files installed, but may not have any other
assemblies installed.
- Create Dependent assemblies
- Just the files in this assembly, but not any imports
- Suitable for installing on a Dynamide server that has the import
assemblies already installed.
- Create WAR files
- These require Monolythic Assemblies
- A WAR file will be produced which is a full deployment image
of your assembly, including all Dynamide assemblies and all required
jar files.
- Deploy a WAR file to a Resin host
- Deploy an assembly to a Dynamide host
- Map URI's to deployed applications in assemblies
- Specify that an application requires certain interfaces
- Specify that an application requires certain build numbers
Directories in Dynamide application server environment
Here is the layout of Dynamide's resources, including your installed
assemblies.
- RESOURCE_ROOT
- assemblies
- com-dynamide-lib-59 -- common assembly with resources
available to all users, version 59
- resources -- all assemblies have a resources
directory , they are not shown for the rest of the shared
assemblies here.
- com-dynamide-lib-60 -- common assembly with resources
available to all users, version 60
- com-widgetco-10 -- WidgetCo's assembly, version
10, available for import. Contains re-usable widgets..
- com-widgetco-11 -- WidgetCo's assembly, version
11.
- com.foobar-lib-20 -- Foobar's assembly, available for
import
- homes
- dynamide
- com-dynamide-apps-59 -- common assembly with applications
available to users who subscribe to the IDE, etc.
- acme
- assemblies
- com-acme-lib-4 --Library of widgets, shared only
among acme's assemblies.
- com-acme-catalog-6 -- build 6 of the catalog applications,
available for Q/A testing
- joe
- assemblies
- com-acme-lib-4 --Library of widgets, shared only
among Joe's assemblies.
- com-acme-catalog-7 -- Joe's development assembly,
build 7
- com-acme-catalog-8 -- Joe's development assembly,
build 8
- css -- Cascading Style Sheets
- widgets -- Widget Library
All searches and named resources are relative to "resources". Since
there are multiple "resources" directories, they are searched in order
as defined by the ResourceManager's resource path. Normally,
this is {assembly}/apps/{app}/resources/, {assembly}/resources, {imported-assembly}/resources,
{imported-assembly}/resources, ... and so on through the list of imported-assemblies.
In this scheme, apps in imported assemblies cannot be searched
for resources. Instead, you must load up the app within your
assembly or the imported assembly, and delegate to it.
Note: user "joe" cannot access files from assemblies in the home directory
of user "acme", even though Joe works for acme. In hosted mode,
Joe must obtain copies of assemblies and place them in /joe/assemblies/
, or arrange to have them installed in /assemblies. To
protect access to assemblies, write a monitor class and name it in
the assembly.xml file in the "monitor" field. The monitor can
accept, deny, and log access. Without a monitor, in Hosted Mode, putting assemblies
in /assemblies is less contained, since other organizations
have access to the assemblies.
Other users can access applications installed in /homes/dynamide, but
not via the filesystem, only through URLs, such as /dynamide/ide.
The apps in dynamide can access files anywhere in the tree because
the SecurityManager installed by the ResourceManager specifically allows
it.
Mapping URI's to Applications (web-apps.xml)
A URI is the path portion of a URL. For example, given the URL
http://myhost:80/foo/bar?param=value
the URI is
/foo/bar
In the web-apps.xml file you describe the apps that are in this assembly,
and what URI's should be associated with them. If you are running
in "Hosted Mode", the URI's will be prepended with the account name.
For example, account "acme" with an app named "demo",
/demo
will become
/~acme/demo
in hosted mode.
Also, if you are running in either Hosted Mode or Self-Hosted Mode, a
user's sandbox will also be accessible by using this URI naming scheme.
For example, if user "joe" has the same application installed in an
assembly in his home directory, then this application is available
via:
/~joe/demo
In Self-Hosted Mode, the administrator has permission to alter the global
web-apps.xml file, and so can remap any URI's.
The context for URI mapping is chained. The root web-apps.xml
is read first, then all the web-apps.xml files from the account home
dirs, then from each assembly. Conflicts are dissallowed and
reported. ".." and path.separator are not allowed.
All APPNAME values are taken to be relative to the directory with web-apps.xml.
Note: still to be worked out -- The WebAppEntry
class in memory fills in the assembly name and home name, based on
where it picked up the web-apps.xml file. This object is in the Dynamide
context. But the contexts are searched in order, so a global web-apps.xml
that specifies that a url maps to a certain assembly wins over the
same url found in any assembly, since the global one specifies the
assembly.
web-apps.xml files within assemblies don't use the ASSEMBLY element,
or the HOME element. Those elements are used or updated when the assembly
is installed. For example, within assembly dynamide-apps-59, the web-apps.xml
file looks like this:
<web-apps>
<app>
<URI>/Shop/Catalog</URI>
<APPNAME>catalog</APPNAME>
</app>
</web-apps>
but once installed in a user's home directory, it should look like this
<web-apps>
<app>
<URI>/Shop/Catalog</URI>
<APPNAME>catalog</APPNAME>
<ASSEMBLY>com-acme-catalog-6</ASSEMBLY>
</app>
</web-apps>
and if installed in Self-Hosted Mode, all entries should be filled in.
<web-apps>
<app>
<URI>/Shop/Catalog</URI>
<APPNAME>catalog</APPNAME>
<ASSEMBLY>com-acme-catalog-6</ASSEMBLY>
<HOME>acme</HOME>
</app>
</web-apps>
There are currently no tools to perform these installations -- simply
edit the files and promote them into the correct directories.
AN IMPORTANT POINT: URI's inside the web-apps.xml file in
an assembly are not consulted at runtime. They are there to help the
manual and automated (not implemented) processes that install the applications.
The result of the installation is updating of the global web-apps.xml
file, or the one in homes/$account, depending on the action taken by the
administrator and the administrator's permissions.
To sumarize, here is a series of web-apps.xml files for a Self-Hosted
Mode host:
- RESOURCE_ROOT/
- assemblies/
- homes/
- acme/
- assemblies/
- com-acme-lib-4/
- com-acme-catalog-6/
The precedence is :
First: homes/web-apps.xml
Second: homes/acme/web-apps.xml
Third: homes/acme/assemblies/com-acme-catalog-6/web-apps.xml
When you log in, you get assigned roles, and permissions. Dynamide
objects require role permissions.
Roles:
ROOT_ADMIN
LOCAL_ADMIN
DEVELOPER
USER
Permissions:
WRITE
READ
Objects:
ROOT_WEBAPPS
HOME_WEBAPPS
ASSEMBLY_WEBAPPS
In Hosted Mode, only the Dynamide host administrator gets ROOT_ADMIN.
In Self-Hosted Mode, you can appoint a list of users to participate in
the ROOT_ADMIN role.
Here are the permissions related to the web-apps.xml file:
Object
|
Example File
|
Write Access Requires
|
Read Access Requires
|
ROOT_WEBAPPS
|
homes/web-apps.xml
|
ROOT_ADMIN.WRITE |
USER.READ
|
HOME_WEBAPPS
|
homes/acme/web-apps.xml
|
LOCAL_ADMIN.WRITE
|
USER.READ
|
ASSEMBLY_WEBAPPS
|
homes/acme/assemblies/com-acme-catalog-6/web-apps.xml
|
DEVELOPER.WRITE
|
USER.READ
|
Directories in Dynamide Source Distribution
- bin -- shell scripts
- build -- Ant destination for output
- doc -- Static documentation for distribution
- javadoc -- Generated javadoc
- doc -- Static documentation
- internal -- Static documentation on Dynamide internals
- lib -- jar files
- src -- Source tree for building dynamide, including resources
- jacl -- Modified files to be merged into Jacl source
tree
- java -- Java source files to build dynamide.jar
- jsp -- Utility jsp's that can be run from App Server
- conf -- Configuration files for Dynamide
- assemblies -- XML files, and other text-based files.
Current versions of Dynamide libs and applications. Use
CVS and Ant to build multiple assembly version targets for distribution.
- dynamide-lib -- current version of Dynamide resources
(Widget sources, javascript, CSS, etc.)
- resources
- css -- Cascading Style Sheets
- js -- Javascript
- widgets -- Widget Library
- xsl -- XSLT stylesheets
- dynamide-apps -- current version of Dynamide applications.
Directories in Dynamide WAR-file Distribution
- WEB-INF -- Ant destination for output
resources -- XML files, and other text-based
files
conf -- Configuration files for Dynamide
sites -- Installed sites, including Dynamide
resource versions
dynamide -- current version of Dynamide resources
(Widget sources, javascript, CSS, etc.)
templates
css -- Cascading Style Sheets
widgets -- Widget Library
users -- Installed Users
- lib -- jar files
- doc -- Static documentation
- javadoc -- Generated javadoc
- internal -- Static documentation on Dynamide internals
- jsp -- Utility jsp's that can be run from App Server
Note: you may have sites outside of the war file also. You
may install these where you wish, accessible to the Resin box via the
(possibly network) filesystem These are configured through the conf/web-apps.xml.
You point to your conf/web-app.xml with a serlet parameter in resin.conf.
You can have multiple web-apps.xml files in the same folder, just name
them differently and register them in the resin.conf file. You would
do this if Q/A and Dev happened to point at the same source, for example.
These are the task involved in installing a new WAR file.
back up conf file
install war file
merge conf file changes in
point conf to local sites file
sites/yoursite/conf contains a backup of conf. (maybe a local conf for
all of this site?)
secure file system resources
set any non-standard ports you use
check resin.conf file
Site file has db connection strings, url mappings