Blog Archives

March 7th, 2011
10:23 am
JUnit testing EJBs with Eclipse / Glassfish 3.0.1 – EJB 3.1 embedded container

Posted under Glassfish
Tags , , , , , ,

Update – Controlling Logging with the JUnit Eclipse Plugin

Controlling logging with the Eclipse JUnit plugin is not obvious and not documented. Even a trawl of the net did not find an answer even though the question was asked on some forums. Fortunately, it is straightforward once you know. By default, JUnit under Eclipse just logs at INFO level. It uses java.util.logging by default, and therefore the way to contol it is as follows :-

1/ Make a local copy of logging.properties from the one under your JAVA_HOME/jre/lib directory – in my case I placed it under <eclipse project>/test, which was the top level test folder.

2/ Add the following VM argument to the run configuration used for JUnit testing of your project (see under Run/Run Configurations):-

-Djava.util.logging.config.file=${workspace_loc:YourEclipseProject}\\test\\logging.properties

The {} construct allows you to conveniently specify the file system path to your Eclipse project. Note that the path delimiters for Windows are escaped as per usual.

3/ Then edit the logging.properties as desired. The comments in the file are pretty comprehensive. Note that the console logger has its own limit on logging level even if you specify a more detailed level for your own package. For JUnit testing, I prefer to disable the console logger and just log to a file, as then I can just refer to the JUnit pane without it being interrupted with the scrolling console log, as a scrolling log goes against the JUnit principle of automated testing anyway. When specifying your own logging file you can use a path relative to the top level project directory, and %h in the name is your user home directory, and %u is used as a version number when successive log files are created with the same name. The following shows my sample logging.properties:-

############################################################
#      JUnit Testing Logging Configuration File – S.E. Woodley
#
# You can use a different file by specifying a filename
# with the java.util.logging.config.file system property. 
# For example java -Djava.util.logging.config.file=myfile
############################################################

############################################################
#      Global properties
############################################################

# "handlers" specifies a comma separated list of log Handler
# classes.  These handlers will be installed during VM startup.
# Note that these classes must be on the system classpath.
# By default we only configure a ConsoleHandler, which will only
# show messages at the INFO and above levels.
#handlers= java.util.logging.ConsoleHandler

# To also add the FileHandler, use the following line instead.
#handlers= java.util.logging.FileHandler, java.util.logging.ConsoleHandler
#
#S.E. Woodley remove the console handler for JUnit testing.
handlers= java.util.logging.FileHandler

# Default global logging level.
# This specifies which kinds of events are logged across
# all loggers.  For any given facility this global level
# can be overriden by a facility specific level
# Note that the ConsoleHandler also has a separate level
# setting to limit messages printed to the console.
.level= INFO

############################################################
# Handler specific properties.
# Describes specific configuration info for Handlers.
############################################################

# default file output is in user’s home directory.
#java.util.logging.FileHandler.pattern = %h/java%u.log
java.util.logging.FileHandler.pattern = test\\JUnitTest%u.log
java.util.logging.FileHandler.limit = 50000
java.util.logging.FileHandler.count = 1
#java.util.logging.FileHandler.formatter = java.util.logging.XMLFormatter
java.util.logging.FileHandler.formatter = java.util.logging.SimpleFormatter

# Limit the message that are printed on the console to INFO and above.
java.util.logging.ConsoleHandler.level = INFO
java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter

############################################################
# Facility specific properties.
# Provides extra control for each logger.
############################################################

# For example, set the com.xyz.foo logger to only log SEVERE
# messages:
com.xyz.foo.level = SEVERE
uk.co.salientsoft.level=INFO

Using Exit Codes when running Scripts etc. for Test setup

1/ In my case I needed to run a SqlPlus script to populate a test database as part of the JUnit test setup. With SqlPlus, it is possible for a script to return an exit code which indicates success, or whether there was an SQL or operating system error such as an error finding a called script. This post here indicates how this can be done. This is obviously highly desirable for JUnit testing as successful script execution can then correctly affect the test outcome via an assert. My ScriptRunner class, mentioned below, returns the exit code from SqlPlus.

2/ I used my ScriptRunner utility class which allows simple property file based setup for running external OS programs such as SqlPlus, and which acts as a wrapper to the standard Java ProcessBuilder class. ScriptRunner will be found in the repository. The sample code at the end of this post has been modified to show the use of ScriptRunner with exit code assert handling, in the @BeforeClass method.

Original Post

The new embedded container in Java EE 6 is a good choice for unit testing of EJBs. It allows standalone testing outside of a full container, and supports CDI and CDI injected beans in EJBs, including the injection of POJOs into EJBs. The following steps explain how to set it up, as their are a  few gotchas for the unwary. There are other approaches to this – in particular there is a distinction between using the embedded API and an embedded container. However, the following approach was commonly used by a number of sites, is straightforward, and ticked all my boxes for JUnit testing of EJBs. A code sample is at the foot of this post.

1/ Add the following embedded container shell jar to your classpath. Failure to do this results in the following error :-

        javax.ejb.EJBException: No EJBContainer provider available: no provider names had been found.

I defined an Eclipse User Library for it:-

        <install-dir>\glassfish\lib\embedded\glassfish-embedded-static-shell.jar

Note that when doing this, the User Library must point to the actual jar in the glassfish instance you are using. You cannot just copy the library to another location and point to it, or you will continue to get the above provider names error. The above jar is a ‘shell jar’ explicitly designed to link an embedded container to an existing glassfish installation. The embedded container uses the shell jar location to detect the glassfish instance to use to obtain the necessary run configuration. For example, if your EJBs make calls to JPA and use a data source named in persistence.xml, then the embedded container will use the data source defined in the glassfish instance you are pointing at.

Some posts talk about having to use the default in-memory data source name when testing, but this is probably due to a difference in the way the embedded container is being configured and used. For example, there are other embedded jars you can use which are not designed to tie in to an existing glassfish installation. In my case this was not necessary and my existing Oracle data source was automatically discovered and used.

2/ Next, add a second copy of beans.xml in src/META-INF (alongside persistence.xml and orm.xml). There is a gotcha here – the full container deployment of a war file needs to see it in WEB_INF, but this will not work for the embedded container. I was unable to find a single location that would satisfy both, and I tried passing properties to the embedded container to get it to see the beans.xml in WEB_INF, but to no avail. Note that if you do not add the second copy as above, you may find that some injection works, e.g. for EJBs into other EJBs, but in my situation I sometimes had POJOs (such as the Apache Base64 encoder) injected into EJBs, and for this to work, you have to get this step right. In the end, I also added a unit test to check that POJO injection was working, with a warning to check beans.xml  if the test failed.

3/ Eclipse (helios in my case) has good support for JUnit 4, and tests and test suites can be run directly by right clicking and selecting Run as JUnit Test or Debug as JUnit test. It also has a wizard to allow creation and maintenance of test suites, but sadly this did not work due to a known bug. The code below illustrates how to create a suite using annotations (you can also do it with code). Creating stubs for unit tests is also easy via right click in the explorer and selecting New JUnit test, and selecting the class to test etc. If JUnit 4 is not already present on your build path, Eclipse will prompt you to add it.

4/ When creating the tests in Eclipse, I added a new source folder just for the tests, as test/src  to keep the tests separate from deployed code. Also, in the build path dialog (right click the project and select Build Path/Configure Build Path), on the source tab I ticked allow output folders for source folders,and added test/classes as the output folder for the tests. Note that after doing this, I visited the deployment assembly property page (right click the project in the explorer, select properties, and select Deployment Assembly in the left hand pane), and ensured that the /test directory was removed to ensure that the test classes would not be deployed in the war file.

5/ When running, I did get a couple of exceptions in the log, from the internal setting up of the embedded container. These did not prevent it from starting or working correctly, and all my unit tests ran fine. They are in fact known bugs (which can be ignored) which have been raised on the Glassfish Jira issue log here and here. Here is a sample of the error traces:-

17-Dec-2011 23:18:09 org.glassfish.flashlight.impl.provider.FlashlightProbeProviderFactory processXMLProbeProviders
SEVERE: MNTG0301:Cannot process XML ProbeProvider, xml = META-INF/mojarra-jsf-api-probe-provider.xml
java.lang.IllegalStateException: Provider already mapped glassfish:jsf:faces-servlet
    at org.glassfish.flashlight.impl.core.ProbeProviderRegistry.registerProbeProvider(ProbeProviderRegistry.java:96)
    at org.glassfish.flashlight.impl.provider.FlashlightProbeProviderFactory.registerProvider(FlashlightProbeProviderFactory.java:521)
    at org.glassfish.flashlight.impl.provider.FlashlightProbeProviderFactory.processXMLProbeProviders(FlashlightProbeProviderFactory.java:360)
    at org.glassfish.admin.monitor.MonitoringBootstrap.processProbeProviderXML(MonitoringBootstrap.java:407)
    at org.glassfish.admin.monitor.MonitoringBootstrap.addProvider(MonitoringBootstrap.java:282)
    at org.glassfish.admin.monitor.MonitoringBootstrap.verifyModule(MonitoringBootstrap.java:219)
    at org.glassfish.admin.monitor.MonitoringBootstrap.discoverProbeProviders(MonitoringBootstrap.java:165)
    at org.glassfish.admin.monitor.MonitoringBootstrap.enableMonitoringForProbeProviders(MonitoringBootstrap.java:539)
    at org.glassfish.admin.monitor.MonitoringBootstrap.postConstruct(MonitoringBootstrap.java:153)
    at com.sun.hk2.component.AbstractWombImpl.inject(AbstractWombImpl.java:174)
    at com.sun.hk2.component.ConstructorWomb$1.run(ConstructorWomb.java:87)
    at java.security.AccessController.doPrivileged(Native Method)
    at com.sun.hk2.component.ConstructorWomb.initialize(ConstructorWomb.java:84)
    at com.sun.hk2.component.AbstractWombImpl.get(AbstractWombImpl.java:77)
    at com.sun.hk2.component.SingletonInhabitant.get(SingletonInhabitant.java:58)
    at com.sun.hk2.component.LazyInhabitant.get(LazyInhabitant.java:107)
    at com.sun.hk2.component.AbstractInhabitantImpl.get(AbstractInhabitantImpl.java:60)
    at com.sun.enterprise.v3.server.AppServerStartup.run(AppServerStartup.java:212)
    at com.sun.enterprise.v3.server.AppServerStartup.start(AppServerStartup.java:128)
    at com.sun.enterprise.module.bootstrap.Main.launch(Main.java:457)
    at com.sun.enterprise.module.bootstrap.Main.launch(Main.java:401)
    at com.sun.enterprise.module.bootstrap.Main.launch(Main.java:310)
    at com.sun.enterprise.module.bootstrap.Main.launch(Main.java:303)
    at com.sun.enterprise.glassfish.bootstrap.ASEmbedded.run(ASEmbedded.java:101)
    at com.sun.enterprise.glassfish.bootstrap.AbstractMain.start(AbstractMain.java:78)
    at org.glassfish.api.embedded.Server.<init>(Server.java:288)
    at org.glassfish.api.embedded.Server.<init>(Server.java:61)
    at org.glassfish.api.embedded.Server$Builder.build(Server.java:158)
    at org.glassfish.api.embedded.Server$Builder.build(Server.java:140)
    at org.glassfish.ejb.embedded.EJBContainerProviderImpl.init(EJBContainerProviderImpl.java:154)
    at org.glassfish.ejb.embedded.EJBContainerProviderImpl.createEJBContainer(EJBContainerProviderImpl.java:114)
    at javax.ejb.embeddable.EJBContainer.createEJBContainer(EJBContainer.java:102)
    at javax.ejb.embeddable.EJBContainer.createEJBContainer(EJBContainer.java:78)
    at uk.co.salientsoft.cheepcheep.service.impl.DomainServiceImplTest.setUpBeforeClass(DomainServiceImplTest.java:44)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:27)
    at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:31)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
    at org.junit.runners.Suite.runChild(Suite.java:128)
    at org.junit.runners.Suite.runChild(Suite.java:24)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:49)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)

(then further down in the log…)

WARNING: Exception while performing resource-adapter’s security permission check :
java.io.FileNotFoundException: E:\Java\Dev\Helios-SR2\Workspaces\CheepCheep\TraderUI\gfembed880784300432477021tmp\config\server.policy (The system cannot find the file specified)
    at java.io.FileInputStream.open(Native Method)
    at java.io.FileInputStream.<init>(FileInputStream.java:106)
    at java.io.FileReader.<init>(FileReader.java:55)
    at com.sun.enterprise.connectors.service.ConnectorConfigurationParserServiceImpl.getFileContent(ConnectorConfigurationParserServiceImpl.java:133)
    at com.sun.enterprise.connectors.service.ConnectorConfigurationParserServiceImpl.getSecurityPermissionSpec(ConnectorConfigurationParserServiceImpl.java:92)
    at com.sun.enterprise.connectors.ConnectorRuntime.getSecurityPermissionSpec(ConnectorRuntime.java:495)
    at com.sun.enterprise.connectors.service.ResourceAdapterAdminServiceImpl.createActiveResourceAdapter(ResourceAdapterAdminServiceImpl.java:239)
    at com.sun.enterprise.connectors.service.ResourceAdapterAdminServiceImpl.createActiveResourceAdapter(ResourceAdapterAdminServiceImpl.java:338)
    at com.sun.enterprise.connectors.ConnectorRuntime.createActiveResourceAdapter(ConnectorRuntime.java:327)
    at com.sun.enterprise.connectors.service.ConnectorService.loadDeferredResourceAdapter(ConnectorService.java:164)
    at com.sun.enterprise.connectors.service.ConnectorService.loadResourcesAndItsRar(ConnectorService.java:133)
    at com.sun.enterprise.connectors.service.ConnectorService.checkAndLoadPool(ConnectorService.java:307)
    at com.sun.enterprise.connectors.service.ConnectorResourceAdminServiceImpl.createConnectorResource(ConnectorResourceAdminServiceImpl.java:91)
    at com.sun.enterprise.connectors.ConnectorRuntime.createConnectorResource(ConnectorRuntime.java:266)
    at com.sun.enterprise.resource.deployer.JdbcResourceDeployer.deployResource(JdbcResourceDeployer.java:107)
    at org.glassfish.javaee.services.ResourceProxy.create(ResourceProxy.java:84)
    at com.sun.enterprise.naming.impl.SerialContext.lookup(SerialContext.java:432)
    at javax.naming.InitialContext.lookup(InitialContext.java:392)
    at javax.naming.InitialContext.lookup(InitialContext.java:392)
    at com.sun.enterprise.connectors.service.ConnectorResourceAdminServiceImpl.lookup(ConnectorResourceAdminServiceImpl.java:203)
    at com.sun.enterprise.connectors.ConnectorRuntime.lookupPMResource(ConnectorRuntime.java:429)
    at org.glassfish.persistence.jpa.JPADeployer$ProviderContainerContractInfoImpl.lookupDataSource(JPADeployer.java:228)
    at org.glassfish.persistence.jpa.PersistenceUnitInfoImpl.<init>(PersistenceUnitInfoImpl.java:108)
    at org.glassfish.persistence.jpa.PersistenceUnitLoader.loadPU(PersistenceUnitLoader.java:130)
    at org.glassfish.persistence.jpa.PersistenceUnitLoader.<init>(PersistenceUnitLoader.java:96)
    at org.glassfish.persistence.jpa.JPADeployer.prepare(JPADeployer.java:121)
    at com.sun.enterprise.v3.server.ApplicationLifecycle.prepareModule(ApplicationLifecycle.java:644)
    at com.sun.enterprise.v3.server.ApplicationLifecycle.deploy(ApplicationLifecycle.java:296)
    at org.glassfish.kernel.embedded.EmbeddedDeployerImpl.deploy(EmbeddedDeployerImpl.java:214)
    at org.glassfish.kernel.embedded.EmbeddedDeployerImpl.deploy(EmbeddedDeployerImpl.java:144)
    at org.glassfish.ejb.embedded.EJBContainerImpl.deploy(EJBContainerImpl.java:128)
    at org.glassfish.ejb.embedded.EJBContainerProviderImpl.createEJBContainer(EJBContainerProviderImpl.java:120)
    at javax.ejb.embeddable.EJBContainer.createEJBContainer(EJBContainer.java:102)
    at javax.ejb.embeddable.EJBContainer.createEJBContainer(EJBContainer.java:78)
    at uk.co.salientsoft.cheepcheep.service.impl.DomainServiceImplTest.setUpBeforeClass(DomainServiceImplTest.java:44)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:27)
    at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:31)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
    at org.junit.runners.Suite.runChild(Suite.java:128)
    at org.junit.runners.Suite.runChild(Suite.java:24)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:49)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
17-Dec-2011 23:18:17 com.sun.ejb.containers.BaseContainer initializeHome

6/ In my case, my project used JPA 2 and Eclipselink, with Oracle XE. Happily I found that as long as I followed the above steps properly, everything ran fine with no messing about and no need for special setup or property passing to the embedded container. It feels a bit like ‘smoke and mirrors’ when you first see it and you wonder how everything is discovered automatically, but once you understand the point about using the embedded shell jar in the actual glassfish instance it all becomes clear. Note that it does not matter whether or not your project is currently deployed to the target glassfish instance – all that matters is that the necessary configuration such as data sources are present and correct.

7/ Note that whilst I did manage to get CDI injection of POJOS into an EJB working as in 2/, I was not able to directly instantiate a POJO from the container context, so for example I could not test a POJO which then called an EJB. It is of course vital that the initial bean under test is created from the container context or it will not run in the container. A number of posts on the net like this one here discuss trying to obtain a BeanManager using ctx.lookup("java:comp/BeanManager") which should work for Java EE 6, in order to use the BeanManager to obtain CDI bean reference from the embedded container context. However, all the posts I found failed to find a solution. This Jira post may indicate the fundamental problem.

I did attempt a workaround – all CDI beans (including EJBs) can obtain a BeanManager reference by using e.g. @Inject private BeanManager beanManager. I therefore tried creating a BeanManagerLocator EJB whose sole job was to inject the BeanManager and return it via a getter. This did allow me to obtain a valid BeanManager. I then tried to get a bean reference to my CDI model bean (a dependent bean used to decouple JSF controllers from the service layer) as follows :-

BeanManagerLocator beanManagerLocator = (BeanManagerLocator) ctx.lookup("java:global/classes/BeanManagerLocator");
BeanManager beanManager = beanManagerLocator.getBeanManager();

Bean<?> modelBean = beanManager.getBeans(Model.class).iterator().next();
CreationalContext<?> cc = beanManager.createCreationalContext(modelBean);
Model model = (Model)beanManager.getReference(modelBean, Model.class, cc)

Unfortunately, the final statement which actually gets the bean reference failed an error, at which point I gave up. Clearly some deeper magic is needed to create the CDI bean outside of the container. It might be possible to achieve this by bootstrapping CDI separately outside the container, and this is certainly possible in Java SE. However, there is then the issue of coupling the CDI environment outside the container to the one inside, so that the whole test environment is integrated like the normal one. I decided that all this was a bridge too far. Here is the error mentioned at the top of this paragraph:-

java.lang.IllegalStateException: No valid EE environment for injection of uk.co.salientsoft.test.view.ModelImpl

 

Whilst researching this, I found the following links useful:-

  • This post uses Glassfish 3.1 and maven, and sets up a custom glassfish configuration on the classpath using domain.xml. Interesting, but I prefer to tie to the configuration of an actual development instance as my configuration is then all centralised, in step, and can be maintained by the glassfish admin tool.
  • This post by Adam Bien is interesting but does not mention how to tie the configuration using the shell jar, and what to do about the above “no provider names had been found” error.
  • This post discusses the concept from a CDI perspective
  • Oracle documentation about the embedded container and embedded API may be found here and here

 

Code Example

AllTests.java

@RunWith(Suite.class)
@Suite.SuiteClasses({
    DomainServiceImplTest.class,
})
public class AllTests {}

DomainServiceImplTest.java

public class DomainServiceImplTest {
    private static EJBContainer ejbC;
    private static DomainServiceLocal domainService;
    
    @BeforeClass
    public static void setUpBeforeClass() throws Exception {

        /* Populate the database with the correct test data */
        ScriptRunner scriptRunner = new ScriptRunner();
        int exitCode = scriptRunner.run("test\\PopulateTestDatabase");

        assertTrue (String.format("SqlPlus script exit code was: %s, should be 0", exitCode), exitCode == 0);

        ejbC = EJBContainer.createEJBContainer();
        Context ctx = ejbC.getContext();
        
       /*
         * List the available ejbs for the container – useful when debugging the test environment
         * The empty name string lists all the top level binding categories
         * java:global/classes lists all the ejbs for the embedded container
         */
        NamingEnumeration<Binding> ne = ctx.listBindings("");       
        while(ne.hasMore()) {
            Binding b = (Binding) ne.next();
            System.out.println(b.getName() + " – " + b.getObject());
        }
        ne = ctx.listBindings("java:global/classes");       
        while(ne.hasMore()) {
            Binding b = (Binding) ne.next();
            System.out.println(b.getName() + " – " + b.getObject());
        }
        domainService = (DomainServiceLocal) ctx.lookup("java:global/classes/DomainServiceImpl");   
    }

    @AfterClass
    public static void tearDownAfterClass() throws Exception {

         // Close the container when done to save resources  
        ejbC.close();       
    }

    @Test public void testCDIPojoInjection() throws Exception {
        assertFalse("CDI POJO injection – embedded ejb container requires 2nd beans.xml in src/META_INF for this to work",
                                domainService.getTreeSearchBuilder() == null);       
    }
    @Test public void testFetchTaxonomiesNotNull() throws Exception {
        List<Taxonomy> taxonomies = domainService.fetchTaxonomies(true);       
        assertFalse("Taxonomies returned should not be null", taxonomies == null);
    }
    @Test public void testFetchTaxonomiesCount() throws Exception {
        List<Taxonomy> taxonomies = domainService.fetchTaxonomies(true);       
        assertTrue("Taxonomies returned should have count of 1", taxonomies.size() == 1);       
    }
    @Test public void testFetchTaxonomiesDefault() throws Exception {
        List<Taxonomy> taxonomies = domainService.fetchTaxonomies(true);       
        assertTrue("Taxonomy returned should be the default", taxonomies.get(0).isDefaultTaxonomy());       
    }
}

PopulateTestDatabase.properties

#ScriptRunner property file to populate test data via SqlPlus
scr.include=sqlplus
scr.name=Populate Test Data

scr.directory=test\\database
scr.param.user=testdb4
scr.param.password=password4
scr.param.database=xe
scr.param.scriptfile=PopulateAll.sql
scr.log.file=..\\PopulateTestDatabase.log
scr.log.append=false
scr.log.console=false

sqlplus.properties  (this property file is standard to ScriptRunner and is run directly from within ScriptRunner.jar)

# ScriptRunner definition for Oracle SqlPlus under Windows

# Give the script a name (this can be overridden by a calling script)
scr.name=SqlPlus

# Define the command and parameters
# Note that under Windows, the command, user/password/database and Sql script
# must all be specified as separate command strings, or SqlPlus does not see the correct arguments.
# Other systems may differ.
scr.command.1=sqlplus
scr.command.2=%1$s/%2$s@%3$s
scr.command.3=@%4$s

#Define named parameters for the arguments to SqlPlus, for the users convenience
scr.param-name.user=1
scr.param-name.password=2
scr.param-name.database=3
scr.param-name.scriptfile=4

No Comments »

March 6th, 2011
8:53 pm
Using the Decorator pattern when extending the underlying Class

Posted under Java
Tags , , , , ,

In some cases, a Decorator just wraps an underlying class and does not add any interface changes of its own – it just changes behaviour without adding any new methods or properties. An example of this would be this ‘coffee’ example in the chapter on the Decorator pattern from the excellent Head First Design Patterns book by Eric and Elisabeth Freeman. In this case, it is not necessary to have visibility of individual decorators in the chain – they all add their required changes to the price and description of the coffee, and calling methods on the outermost decorator causes all the inner ones to be called to do their thing.

In other cases, however, it is necessary to add new methods and properties to a Decorator. An example from later in the same chapter would be the LineNumberInputStream decorator in the standard java.io package. this performs line numbering on the lines that pass through it, so it is obviously necessary to use the properties of that particular decorator in the chain to fetch the line numbers.

Therefore, in cases like this, client code will need to refer to particular decorators in the chain to access such methods and properties. This in no way invalidates the decorator pattern – it is important to note that we have still extended the underlying class using the open/closed principle, i.e. we have not modified it but decorated it with one or more new classes. Also and equally importantly, the various decorators in the chain are completely decoupled both from the underlying class and from each other as well.

There will be occasions where a decorator needs to extend the behaviour not just of the underlying base class, but also some of the behaviour of another decorator. In this case, such a decorator will extend the decorator it is adding behaviour to, rather than the underlying base class. The general guiding principles here are as follows:-

A decorator should extend the lowest level class it needs to in order to perform its function. For example, if A is a base class and B and C are decorators, C should not extend B unless it actually has dependencies on B’s additional behaviour, as otherwise we are introducing unnecessary coupling between objects that do not need to be coupled.

Note that all the decorators can and should be generic. Any subclass of the class a decorator extends may be passed to it, and may be retrieved generically. For example, if class ClassB decorates class ClassA, then we would declare B as follows:-

public class ClassB<C extends ClassA> extends ClassA {

private C decoratedClass;

}

This allows ClassB full access to all of the ClassA methods and properties, even when it is passed an arbitrary subclass of ClassA. Also, we have ensured that we can generically access via a ClassB instance, the particular subclass of ClassA used as the decorated class.

When we need to access particular decorators in a chain, we can either remember the object references used when we created them, or we can fetch references to them from their container decorator. In this case, we obviously have to keep knowledge of how the decorator chain was set up, and what was decorated in what order.

Decorators are a powerful pattern for flexible behaviour extension, but can have their downsides. You can end up with a large number of small decorator classes and large decorator chains – just look at the java.io package to see this. Also, you have to create all the delegated methods and properties for every decorator, although if you are using an IDE like Eclipse this can all be done automatically for you which is a big boon when using decorators heavily, and eliminates a lot of sources of error. Also, the major benefit compared with static extension of a class to add behaviour is that you can set up a decorator chain with any decorators you like in any order – illustrating again the benefits of favouring composition over inheritance.

No Comments »

March 6th, 2011
7:47 pm
Adding jsf view state to domain objects–part II

Posted under JSF
Tags , , , , , , ,

My original post on this is here.  It links to an Icefaces post which discusses using a decorator to do this. The fundamental problem is that you often want view state such as (but certainly not limited to) a selected flag on objects e.g. in tables. However, you do not want to pollute domain classes with view state, so it would not be desirable to add a selected flag to your domain objects as this blurs the layers (especially as you may have multiple different UI layers on the same domain, such as JSF browser clients, smart phone web clients, web services etc. all with different needs). Other examples of view state might be style classes to be used on different table rows in response to use actions etc.

Since my original post I have looked at other ways of achieving this, and summarize various approaches below which could be used to add view state to rows of a table.

In each case, assume initially we have a JSF table of the form <h:dataTable var=”row” value=”#{mainBean.rows}”>, where each row object has the properties firstName and surname, plus the need for a selected boolean flag to be maintained separately from the row.

 

1/ Using a row decorator

My original post discusses using a decorator to add the extra state, as per the icefaces post. This involves wrapping every row, but is transparent to the code. The downside of the decorator is that each domain class requiring the extra state needs its own decorator even though each case might require the same extra state. This potentially means a lot of extra classes just to add a selected flag.

 

2/ Using a generic row wrapper class composed with the row

A second alternative which is similar to the decorator would be just to use a wrapper class which holds the extra state plus the domain class instance, and explicitly make the calls to the domain class methods and properties. Thus, the following code might be used to read our table row properties and the selected flag (all the examples use direct instantiation for simplicity) :-

//wrap a row. rowWrappers is the list containing the wrapped rows
rowWrappers.add(new RowWrapper<Row>(row));

// read properties on a facelets page – note that the table now contains wrapped rows:-

<h:dataTable var=”rowWrapper” value=”#{mainBean.rowWrappers}”>,
<h:outputText value=”#{rowWrapper.row.firstName}”>
<h:outputText value=”#{rowWrapper.row.surname}”>

//read the selected flag on a facelets page
<h:outputText styleClass=”#{rowWrapper.selected ? ‘style1’ : ‘style2’}” value=”…”/>

The pros and cons of this approach are:-

  • All the rows need to be wrapped as before.
  • All the ‘delegation’ to access row properties is explicit in all the expressions.
  • The upside however is that to add a given set of view state properties, only a single class is needed and this can wrap any number of domain classes generically, which can be a significant advantage.

 

3/ Using a Map to hold the additional row state objects

A third approach makes use of the fact that JSF EL value expressions can transparently read Map entries just like properties. Therefore where object m is a map or object that implements java.util.Map, the equivalent expressions m.property1 and m[‘property1’] when reading a value (i.e. on the right hand side of an expression, or rvalue mode) both result in

m.get(‘property1’)

being executed. When writing a value (i.e. on the left hand side of an expression, or in lvalue mode), as in m.property1 = rhsexpression, the statement

m.put(‘property1’, rhsexpression)

will be executed, assigning rhsexpression as the value of property1.

This technique allows us to use the row object itself as a key to the map containing the additional row state:-

//add row state object to map
rowFlagsMap.add(row, new RowFlags());

// read properties on a facelets page :-

<h:dataTable var=”row” value=”#{mainBean.rows}”>,
<h:outputText value=”#{row.firstName}”>
<h:outputText value=”#{row.surname}”>

//read the selected flag on a facelets page using the current row as a map key
<h:outputText styleClass=”#{mainBean.rowFlagsMap[row].selected ? ‘style1’ : ‘style2’}” value=”…”/>

Note that the nested expression evaluation works correctly with the map as the ‘man in the middle’ and that the expression mainBean.rowFlagsMap[row].selected could be used equally to fetch any other property from the rowflags object instead of the selected  property. The expression works as we would expect in both lvalue and rvalue modes, such that if for example the above property value was written to as true from the jsf page (e.g. from the value property of an updated check box we had just ticked), the expression would execute correctly as

mainBean.rowFlagsMap.get(row).selected=true;

The pros and cons of this approach are:-

  • We need an extra map access to get the row state, but for typical table sizes a hashmap would give very efficient access and should not be an issue.
  • We need to use the more complex expression mainBean.rowFlagsMap[row].selected  to fetch the additional row state. However, the plus is that we do not have to wrap each row in the code, and assuming that there are more table properties than additional state, we do not have to explicitly use a nested expression for them as we would in the previous approach.
  • When using this approach, it must be born in mind that you are using an object as a Map key. This should not be an issue, but if you override the hashCode function such that the hash value could change during the lifetime of a row object (for example if a row property changed) you would need to take account of this. Note also that rows in the map will only correctly match the exact same objects. If you refetch the same domain objects again from your entity manager you cannot expect them to match any existing objects in the map. Again, this should not normally be an issue as you would expect to rebuild the map from scratch when refetching domain objects from persistent storage.

 

4/ Using a Smart Map Interface to implement a selected property by storing the selected row objects

This approach is similar to the previous one, in that it uses a Map interface to hold a selected flag. The difference is that we implement our own class implementing  the Map interface and hide a map behind it. Our Map class simply stores each selected row in a ‘real’ map. When the caller reads the selected flag for a row by calling map.get on our map class, we perform a contains call on the ‘real’ map and return true if the row is present, or false if it is not. Similarly, when asked to set selected =true for a row, we just add the row to the ‘real’ map. When asked to set selected=false for a row, we remove it from the ‘real’ map. The pros and cons of this approach are:-

  • We only need to store the selected rows in the map, so we are storing less map entries.
  • The expressions to check the selected flag are a bit simpler, requiring something of the form mainBean.selectedMap[row]
  • Conversely, we need to implement the smart map – this needs quite a number of dummy methods when implementing the Map interface. When implementing this, I typically create an abstract base class which dummies out most of the java.util.Map methods which I don’t need, and then extend this for a desired implementation. This project in the repository makes use of this technique – see the classes uk.co.salientsoft.view.JSFValueMap and uk.co.salientsoft.view.SelectedMap.
  • The other downside is that this method only allows storage of a simple boolean based on the presence or absence of a row. If we need more additional row state, we need to look to one of the other methods.
  • As with the previous method, we are using a row object itself as a map key, so the same caveats apply as in the previous case.

 

Conclusion

As is often the case, there is no clear winner – you take your pick depending on individual requirements and the various pros and cons. Overall, my current favourite in general is to use the additional Map. It is simple to implement (you don’t need to dummy a load of Map methods like you do with the smart Map). Unlike the smart Map, you can add any number of additional properties to a row. The domain row properties can be accessed exactly as before, and you don’t need to wrap every row (however you do need to create the row state object and add it to the map for every row). Whilst the access to the additional state requires a slightly more complex expression, this is likely to be needed less often than expressions to read the domain properties.

No Comments »

March 4th, 2011
5:48 pm
Breadcrumb Composite Component using ui:repeat

Posted under JSF
Tags , , , , , , ,

Update 16/1/2012

A bug was found in the crumb styling. max-width was correctly set on the crumbs to truncate them, but when white space is present in a crumb, the default is to wrap at the max-width. This causes the breadcrumb to increase in height and add a second line. The fix was to turn off the wrapping by setting “white-space:nowrap” in the css for the crumb anchor tags (see Mantis issue 99 for details) :-

.ss-breadcrumb ul li,
.ss-breadcrumb ul li a {
    overflow:hidden!important;
    display:inline-block;
    white-space:nowrap;
    text-decoration: none;
}

 

Original Post

This follows on from my previous posts on the Primefaces breadcrumb here  and here.

I found a couple of further important issues I hit when using the standard breadcrumb:-

  1. In order to add and remove crumbs dynamically, it uses the Primefaces MenuModel. Methods of the MenuItem class are used to add actions and listeners.
  2. The mechanism seems somewhat cumbersome. In particular, it does not appear to be easy to pass a particular target object as an argument to an action or listener method, as the binding appears to be created as a string. Ideally what I would want is for the breadcrumb entries to be created by iterating a list using a var attribute like a table, and then to pass the var object containing the current crumb in the list as an argument in a method call to an action when that crumb was clicked.
  3. The only way I could see to do it involved passing an identifier for an object (such as the primary key for an entity). Whilst I certainly did not bottom it out completely, the mechanism seemed somewhat complex to use and lacking in flexibility.

Adding these issues to the ones already highlighted in the other posts (in particular the slowness of the jQuery operations when initially collapsing a breadcrumb in preview mode), I decided to take the step of rolling my own custom breadcrumb. The following approach was taken:-

  1. I decided to use a composite component rather than create a full blown custom component in code, as this looked more straightforward, and I had experience of composite component creation.
  2. The key factor which made this possible was that I could use ui:repeat to build the breadcrumbs dynamically from a list.
  3. Conditionally rendered xhtml tags could be handled using ui:fragment within the ui:repeat loop. This allowed the use of the rendered attribute on ui:fragment to optionally render sections even when standard non-jsf html tags such as <li> were used. For example, the root crumb of the component is rendered differently to the others, using an icon only. Also, full width crumbs are rendered differently to truncated crumbs (when truncating the component to fit a target width)

The following are the key features and design points for the breadcrumb:-

  1. The component is designed specifically for dynamic use, being driven from a list much like a table. It is not possible to build it statically on the facelets page (static use is covered by the standard control so this was specifically a non-goal/non-requirement).
  2. It is rendered entirely statically, so there is no (potentially slow) javascript/jQuery stuff going on at render time or during use.
  3. Compression to fit a target width is done by passing the desired target width in to the control. This is then used to set max-width css properties on the crumbs. This allows the crumbs to take the width they need and to only be truncated when they hit the max value. The max value is calculated on the server at render time by dividing the max target width by the number of crumbs to be rendered (allowing for the root crumb as a special case).
  4. The full text for a crumb can be viewed at any time by hovering over the crumb – it is displayed using the HTML title attribute. This is one annoyance with the standard Primefaces control – it does not allow use of the title attribute. Using the title  attribute allows the control to be static on the page for speed but still allows truncated crumbs to be easily read.
  5. The component supports the concept of stale crumbs. The idea is that when moving back up the crumb path (leftwards, or navigating up a tree path), the crumbs to the right which were previously visited are not immediately removed. They are highlighted differently as non bold and italic to make them less important compared to the ‘fresh’ crumbs on the path. In addition, the current crumb is underlined in order to make it completely clear where the current position is. Without stale crumbs present, this would normally be the rightmost crumb, but this will now no longer be the case if stale crumbs are present.
  6. Stale crumbs are only removed if the user navigates down a different tree path which invalidates them, in which case they disappear. Provided the user remains on the same tree path, the crumbs will be left in place.
  7. The stale crumbs may be clicked for navigation just like the fresh ones, to allow the user to revisit old ‘stale’ locations. When a stale crumb is revisited, it changes back to a fresh crumb again (as do all other stale crumbs to its left) and it becomes the current crumb – it is therefore rendered in bold, non-italic, and is underlined. The crumbs to the right of it if any still remain stale as they were before.
  8. To assist navigation up a tree structured hierarchy, it is common to include an ‘up’ button somewhere. This is taken a step further by including both up (= left pointing) and down (=right pointing)buttons on the left hand side of the breadcrumb component. When combined with stale crumb support, this feature allows easy navigation both up and down a given tree path. The right button is only enabled when stale crumbs are present, and clicking it moves down the stale crumb list just as if the next stale crumb was clicked. Navigating to the root of the tree (leftmost crumb) disables the left button.
  9. The component is styled in a similar way to the standard Primefaces component, and uses the same CSS classes for the styling.
  10. Styling may be modified, and features such as up/down support turned on or off.
  11. The component is styled using an inner div which holds the component itself – this can be floating if desired in which case it resizes the width to hold its contents. The inner div is contained in an outer div which is typically fixed in size to suit the page, allowing the inner div to scale up to that size. The width used for crumb truncation calculation is passed separately into the control – this will normally be slightly less than the max width set for the divs.
  12. The component is backed by a controller backing bean, BreadcrumbCtrl/BreadcrumbCtrlImpl, which may be subclassed to allow further customisation. The crumbs are passed into the bean as a simple generic list, and a property name used for the crumb text display is passed as a string attribute to the composite component. The controller fields action and listener events from the component, and passes them on using a BreadcrumbEvent interface – an object implementing this interface is passed into the controller bean at init time. When the user clicks on a crumb, the actual crumb in the list plus its list index are simply passed to its action method. When multiple components are used on a page, each will have their own controller object. These will typically be injected into the page backing bean e.g. by CDI as dependent beans. When the action and listener events are called, the actual controller object is also passed. This would allow for example the page backing bean to implement BreadcrumbEvent and manage actions for a number of dependent breadcrumb controllers, using the passed controller object to determine which one was clicked.

The following are some of the key technical issues which arose during development of the component:-

  • ui:repeat is used for iterative xhtml generation of the crumbs. This uses a var attribute like a table to represent the current object (crumb) in the list. It also supports a varstatus attribute which allows access to various loop properties within the loop, such as the current loop index, first and last boolean properties and others. The index property in particular is used to determine styling for the current crumb and stale crumbs etc.
  • In addition, the varstatus object (com.sun.faces.facelets.tag.jstl.core.IterationStatus) can be accessed from the controller bean using code similar to the following, where varStatusKey is the name given in the varstatus attribute to ui:repeat:-

Map<String, Object> requestMap = FacesContext.getCurrentInstance().getExternalContext().getRequestMap();
IterationStatus varStatus = IterationStatus) requestMap.get(varStatusKey);

  • It is important to note that whilst it is tempting to cache the varstatus object in the controller bean, this does not work – a new object must be obtained each time using the above code.
  • ui:fragment can be used directly in the ui:repeat loop within the composite component implementation – it is not immediately obvious from the documentation that this is the case.
  • When declaring the attributes for the composite component using <composite:attribute>, note that the type attribute allows specification of a particular object type, the required attribute makes an attribute mandatory, and the default attribute sets a default.

The source code and a usage example of the breadcrumb control may be found in the repository here.

No Comments »

January 26th, 2011
11:48 pm
Oracle Sql*Plus Nested Scripting, Parameters and Exit Codes

Posted under Oracle
Tags , , , , ,

Update 29/3/2012 – SP2-0310 error due to backslash “\” in parameter

SQLplus has a bug whereby if call to a subscript in the same directory has a command line parameter with a backslash in it, SQLplus messes up the default directory processing and cannot find the called script. It seems to think that the backslash in the parameter is part of the called script file path.

To get around this and avoid hard coding the subdirectory in this script, I pass the subdirectory in from the caller.

Note that this issue may well be the same issue listed below in connection with the use of forward slash “/” causing default directory issues.

A second bug is also present, whereby &1 only works the first time. When used a second time, it incorrectly replaces it with the &1 parameter for the last called script, rather than using the one passed in from our caller. It may be that these &1-&n parameters are global in nature, rather than per level. To get around this, I use an explicit named define for the &1 and use that instead.

The following illustrates the problems:-

–This works ok assuming AddDomain.sql is present in the same directory as this script
@@AddDomain ‘1’  ‘!’

–This will fail with an SP2-0310 error
@@AddDomain ‘1’ ‘\’

The following fix resolves the problem:-

Calling script Main.sql

–We pass the script its own subfolder to get around an SqlPlus SP2-0310 bug, see Lookups.sql
@@Lookups\Lookups ‘Lookups’

 

Called Script Lookups.sql

/*
* SQLplus has a bug whereby if a parameter has a backslash in it,
* SQLplus messes up the default directory processing and cannot find the called script
* It seems to think that the backslash in the parameter is part of the called script file path
* To get around this and avoid hard coding the subdirectory in this script,
* we pass it in from the caller.
*
* A second bug is also present, whereby &1 only works the first time.
* When used a second time, it incorrectly replaces it with the &1 parameter
* for the last called script, rather than using the one passed in from our caller
* It may be that these &1-&n parameters are global in nature, rather than per level.
* To get around this, we use an explicit named define for the &1 and use that instead.
*
* These 2 bugs are awful – I’m not impressed!
*/

define dir=&1
 
@@&dir\AddDomain ‘1’  ‘\’
@@&dir\AddDomain ‘2’  ‘\reports’

These fixes resolve the problem.

 

Update – Parameter passing, use of “/”  and default directory issues

These issues came about when switching to the command line sqlplus utility rather than using Toad as I had before.

  1. If a parameter passed to a called script (in this case via @@) contains a slash “/”, Sql*Plus gives an SP2-0310 file open error. The error is nothing to do with opening the file, but is due to the slash. Escaping it was no help. I was using the slash as a date delimiter for a constant date string passed to the called script, so I just switched this to a dash “-“ instead and changed the to_date string in the called script to ‘YYYY-MM-DD HH24:MI:SS’. This solved the problem.
  2. If a script called via “’@@” is followed by a “/”, then the script will be called twice. Whilst it is normal to follow an SQL command with the slash, this must not be done when calling a script.
  3. When a relative path is used to call a script via the “@@” command, the default directory for the relative path is not the directory of the calling script, as you might expect, but rather the top level default directory. This is rather nasty and inconsistent in my view, but is simple to fix once you know.

Update – Return Codes from Sql*Plus

Sql*Plus can be configured to return an exit code to the calling operating system, to indicate either an OS error (such as a file open error), or an SQL error. This is extremely useful for detecting the success or failure of a script run – for example, I use it during JUnit testing when running scripts to set up a test, as there is then no need to scan log files and you can then just look at the test outcome (which is a central goal of JUnit).

To do this, just add the following at the head of your top level script. This will cause the script or any of its called scripts to abort with an exit code when it fails for any reason:-

WHENEVER OSERROR  EXIT 1
WHENEVER SQLERROR EXIT SQL.SQLCODE

The OSERROR unsurprisingly deals with OS related errors. Unfortunately, it does not appear to be possible to return the actual OS error, so in this case I have returned value of 1 which is a Windows ‘illegal function’ error, which is also what is returned when you copy or rename an invalid filename for example. The SQLERROR returns the actual Oracle error code. These codes are returned to the operating system, and for example under Windows may be detected by testing the %ERRORLEVEL% value as per normal with Windows batch files. I have yet to try this under Linux but the mechanism is similar.

Update – Verify and echo

When debugging a script, it is often useful to log each statement in the output (echo), and also to check how parameter substitution was performed (verify). To do this, just add the following to the head of your top level script. To disable them, just use off instead of on:-

set verify on
set echo on

 

Original Post

This post details some common pointers and gotchas when using nested scripts in Sql*Plus, and passing paramters to a nested script.
The examples were all executed with Toad, which is subset compatible with Sql*Plus, so the points here should work with either.

  1. Use @filepath to call a nested script with a full file path. The default file type is .sql.
  2. A common technique is to place all related scripts and sub scripts in the same directory. If you do this, use @@filename instead with just the filename, and SQL*Plus/Toad will assume that the called script is in the same directory as the executing one. This allows a collection of scripts to be moved to any desired directory and still call each other correctly with no changes.
  3. Parameters may be defined with the define  command as in the example below. Defined  parameters are global and visible to a called scripted even if defined in the calling one.
  4. Parameters are referred to using &name for a defined parameter, or &1, &2 for the first or second parameter passed to a script.
  5. When passing parameters to a script you must delimit them with spaces and must have single quotes around the parameter values, which will allow the parameter value to contain spaces. Note however that you cannot pass an empty string using two quotes ‘’ as this gives a missing parameter error. Oracle treats an empty string as a null anyway, so you should pass the null value differently, e.g. using null.
  6. If you use &name for a parameter you have not previously defined, you will be prompted for the value each time you refer to &name. If you use &&name you will only be prompted for the value the first time, and it will stick from then on and you will not be prompted. If a variable has been previously defined you just use &name all the time and the defined value is used – you will not be prompted.
  7. When defining a parameter or passing one in a call to a sub script,  put single quotes around the value. These will be stripped off when you refer to the parameter, so you will need to add them back when referring to the parameter if you are using a quoted string, for example ‘&1’ or ‘&param’. Double quotes did not work correctly with Toad (not sure about Sql*Plus) so are best avoided.
  8. Due to the above quote handling/stripping therefore, it is not straightforward/posible to add your own secondary quotes to pass a quoted string with the quotes already present. You must add the quotes in the called script, which means that you must decide whether you are passing a constant string (which will have quotes added by the called script), or an expression (which will not have quotes added). There is not a way I could find to pass a value which can either be a quoted string or expression. In practice, this tends not to be an issue and you can work within the limitation, unless you are trying to make scripts fly to the moon – don’t – they are not programs!
  9. If you want to append alphanumerics immediately after a parameter expansion, place a dot after the parameter name, and the dot will be removed, for example &param.xxxx will substitute the definition of param and concatenate it directly with xxxx. Set Concat lets you define the concatenation character to be used, period (dot) is the default.

The documentation for Sql*Plus may be found here. In addition, this is a useful site detailing a number of the features (although it gets the meaning of & and && the wrong way around!)

Simple Example of Nested Scripts with Parameter passing

Test1.sql

define Table = ‘dual’
@@test2 ‘dummy’ ‘X’

 

Test2.sql

select * from &Table where &1 like ‘&2’
/

No Comments »

January 19th, 2011
7:39 pm
Using a Command Pattern for EJB method access

Posted under EJB
Tags , , , ,

Further Update 26/1/2012 – Return Status vs Exceptions in EJB methods

A further  design point has come up re the choice between returning a status enum or throwing exceptions in EJB methods. This also impacts the use of Command Patterns and in particular the status enum idea below. I have posted on this issue here.

 

Further Update 26/1/2012

  1. Another nice feature would be the ability to check the status of a command after it executed generically and then take a decision on whether to continue with the rest of a CommandList.
  2. If this check could be done in the CommandList execute() loop, it would avoid the need for custom initialisers just to abort after a status return. This would avoid the need for the anonymous inner initialiser classes, finals for all the Commands, and constructor injection for all the final Commands.
  3. The initialiser feature is a nice to have, but messy just for simple generic status checking.
  4. A flexible way to do this would be to add a status enum to each command, and then in the base results class, have an EnumSet of values from that status. Adding it to the base results ensures it gets copied back along with everything else.
  5. If a command succeeded with no issues, it would just return null for the status. If there were any ‘issues’ with the result, it return a status code from the enum saying what happened. This would be done in the actual command subclass, just after calling the actual SSB method, when building the results object to be returned.
  6. When using a Command in a list, you would then pass in an EnumSet of status codes for which execution is allowed to continue, to the actual command object generically (via a generic method of Command). Execution would continue either if the status was null, or if it was contained in the set. If non null and not in the set, then a CommandList would stop execution at that point and return what it had done so far.
  7. A further enhancement to 6. could be to also pass in a ‘default action’ enum value to indicate the default action (abort or continue) when a non null status is present. Then this enum value defines the default action, and the EnumSet defines the exceptions to the default, i.e. “abort on all non null statuses except  continue for any in this set” or “continue on all non null statuses except abort for any in this set”.
  8. If the feature was not needed, it could default to null status returns and a CommandList would always carry on (subject to what any Initialisers do)
  9. The feature adds flexible decision making for a CommandList about continuing, allowing checking for multiple status codes via the EnumSet, but in an entirely generic way which does not involve initialisers.
  10. An EnumSet is also efficient and compact, as it is implemented as  a bit mask, and typically a Command will only have a few statuses in its enum.

 

Update

  1. A better technique to fetching the results would be to do it automatically in the Invoker after the results are returned. This has the following advantages:-
  2. The caller has no work to do – for a command list, the results would be immediately available in the original passed in Command/CommandList. If a CommandList was passed, then the individual Commands used to build it would be populated and would be referred to directly so that the correct result subclass could be referenced.
  3. The best way would be for a Command/CommandList to do this generically by passing the original command list in rather than the current varargs mechanism. There is no point in just fetching some of the results as they will all be needed.
  4. Doing it this way presents even less risk of mismatching the command objects to their results – it is automatic and the caller cannot get it wrong. In particular it is not possible to fetch results into the ‘wrong’ command object.
  5. To do this, the fetching needs to be done in the caller’s context, not that of the Invoker (which is an SSB). This could be done by calling a static invoke method on the invoker and passing the invoker SSB and command/command list to it. The static method would then do the ‘real’ invoke, and then do the fetching directly afterwards, directly into the command/CommandList passed by the caller. This static method would therefore not return anything :-

Invoker.invoke(invoker, myCommandList);

Original Post

A command pattern provides a number of advantages for EJB method calling to stateless session beans, at the expense of having to wrap the EJB methods in command classes :-

  1. It provides a convenient and tidy way of performing a number of EJB method calls, specifically to stateless session beans, in a single transaction, by wrapping them in an outer Command List which is itself a command (a macro concept). This then means that only a single call is needed to the EJB container to establish transactional context, by calling a standard command invoker which is itself an EJB.
  2. When wrapping a number of EJB calls in this way, the interface is much cleaner than trying to roll your own higher level method call which calls all the others. When rolling your own, passing in parameters cleanly for a number of EJB calls can be complex, and packing the returned data for convenient retrieval is also a more complex issue. With a command list, each command in the list has its own call parameters, set up and stored in the command object when it is created. Each also has its own return object, retrieved using a convenient standard mechanism.
  3. Add hoc lists of commands can easily be created, as the list does not need to be hard coded.
  4. All the underlying EJB calls can of course still be used, so commands can be used on an as needed basis if it is deemed overly complex to use them throughout. However, there are advantages if they are used consistently, as other parts of a design can then rely on command usage.
  5. A command list can be used as a ‘drop box’ of commands, decoupling different client objects of the drop box from each other. This allows a single transactional context call to be used to execute all the commands, but the client objects need have no knowledge of each other or of the other commands in the drop box. An example of this might be different sub areas of a page which post commands into the drop box command list, and the list is executed by a submit button for the whole page. The sub areas of the page need have no knowledge of each other but can still share the same outer EJB call to the invoker of the command list, such that a single EJB container call results (indirectly) from the submit button.
  6. An initialisation mechanism allows initialiser objects to be attached to each command. This allows later commands in an ad hoc list to have inputs which depend on the output of earlier commands, but still having everything running as a result of a single EJB call to the container. The initialisers are typically anonymous inner classes passed in to a command object when it is set up. Each initialiser is called just prior to execution of the command it is attached to.
  7. The command objects will typically be called from a JSF model bean in a JSF environment.

The main disadvantages are as follows :-

  1. The EJB method calls need to be wrapped in Command classes, so extra coding is needed. However, this  is straightforward and follows a standard pattern.
  2. Some extra complexity arises when command lists are used, in order to unpack the results afterwards. However, this all follows a standard mechanism and importantly does not rely on any error prone use of hard coded list indexes to unpack results.
  3. If custom initialisers are used, the anonymous inner classes which are typically used make the code somewhat more complex. However, if certain lists of commands are commonly used they can and should be combined into a hard coded command list/macro. If this is done, the initialisation can be performed inline as the commands are called, rather than having to be passed in as in the case of an ad hoc list with initialisation.

A sample implementation of this may be found in the repository here.

Key design points for the implementation are as follows :-

  1. The command objects themselves are stateful (as they hold any passed parameters and results, and for a command list, the list of commands). They are not EJBs themselves, but they do refer to the actual EJBs being wrapped. The Invoker is an EJB, albeit a standard one, and is passed the commands to be invoked. Creation of the transactional context happens when the invoker is first invoked. All calls to the underlying EJBs (from the execute methods of the command objects being invoked) are then calls made within the same transactional context already established in the container, and so require much less overhead, and are of course part of the same transaction.
  2. CDI is used throughout for dependency injection, both on the EJBs and on all the commands. The commands must be injected with CDI as they themselves must also have EJB references injected into them – this will not happen correctly if a command object is just created via new, as it will not be properly under CDI control to allow the injection to take place. However, as Command Lists are purely containers for commands, and do not themselves have any CDI dependencies/any references injected, they can freely be created with new if desired. For example, A Command List may be created with new, have all its constituent commands passed into its constructor, and be created directly in the argument list of a call to the invoker, as in the code example above.
  3. A command list is literally a list of commands executed in list order.
  4. As a command list is also a command, lists may be nested – it is entirely possible for a command in a list to itself be another command list.
  5. When a command (or a command list, as it is also a command) is executed, it returns a new instance of its own class containing the results object as the return value. This is necessary as when calling into an EJB container, modifications to properties of parameter objects passed in are not normally visible on return from an EJB container. The only means of returning data is via the method return value. Whilst this behaviour can be overridden in some cases with EJB container settings, this was deemed highly undesirable, and is particularly an issue when the call is to a remote interface. It is important to understand the distinction between the methods of Command objects and Command lists which are called only in the client environment, and calls made into the EJB container (possibly remotely). Calls made in the client environment do allow changes to passed object properties – this is necessary for example to store the listIndex in a passed Command object when it is added to a Command List (see later in point 12), and also when fetching the results back via the fetch method after invoking a Command list (also in point 12). This behaviour is also used by a number of the Java APIs – for example, Collections.sort() sorts the passed list argument, but does not have a return value from the method. Conversely, when the Invoker object is used to invoke (execute) a passed command, the invoker is an EJB (stateless session bean), so the client is calling into the EJB container and establishing transactional context (the call may also be a remote one over RMI if a remote interface is used). In this case, the story is very different, and changes are only passed back via the method return value.
  6. Note that the client environment will often also be within an EJB container – Command objects will typically be invoked for example from a stateful JSF model bean, which may often be in the same Java EE container as the EJBs. However, they are not created in transactional EJB context, so whilst for example they may be created and hosted in Glassfish (which will also be responsible for providing CDI services among many other things), they are not created in its EJB container – they are passed into the EJB container via the Invoker which is itself an EJB (stateless session bean).
  7. Commands and Command lists are implemented using a Composite pattern based on an abstract Command class. This design choice was adopted as it became necessary for the Command base abstract class to have knowledge command lists. For example, a command must have a listIndex property which is used to hold its position in a command list if it is added to one, even though this has no relevance to a standalone command. Also, when command lists are themselves nested inside other command lists, the structure genuinely becomes composite so it is easier to be able to declare all member types generically using a standard abstract base Command class.
  8. A command class typically wraps all the overloaded method calls for an EJB method. This is convenient as a command must have a single return type, but allowing the overloaded methods with different call parameters to be encapsulated in the same command class reduces the number of command classes and eliminates unnecessary clutter. When implementing this, the command class has a set of method calls which mimic the method calls to the underlying EJB. The difference is that rather than calling the EJB, these method calls just store the parameters as properties of the command for later use when the command is invoked by the invoker. When implementing this, an enum (CallType) is used to define which overloaded method is being used. The enum value is set when a particular overloaded method is called. Later, when the command is invoked, the enum is used to determine which corresponding overloaded EJB method to call. This mechanism avoids arcane decoding of null parameters to try to decide which call is in use, and is completely transparent. When these methods on the command class are called, they typically return a reference to the command object as this is often useful. For example, the return reference might be used in a call to add the command to a new command list directly.
  9. When creating a fixed command list to be reused, it is easier and clearer just to extend Command and embed commands in a simple outer ‘macro’ command. Whilst it is possible to create a fixed list by either extending a CommandList or composing one, it turns out that this is slightly longer than just extending a Command, and the code is significantly more complex to understand. A comparison was done in an early version of the Command pattern implementation here. (Note that this is an old version and should only be used for reference. The link given further up is the latest version which is an EJB sample and should be used to base other code on.
  10. Each command has an inner class containing its results to be returned, together with a reference property to an instance of the inner class. The results are unique to the command class and are only used once, so the inner class avoids clutter. The inner class extends a base CommandResult inner class in the base Command class. This allows the results for a command to be reassigned polymorphically to the result property of another object – a trick which is used when accessing the results of commands from a command list. Note that a command class should use delegated property access to get the results – i.e. the command class itself will have property getters for all the result properties, but will get values directly from the result object members. This saves another level of nested reference by the client of the command object when accessing results. Note that when accessing result object members from within the command class, they are access directly without using getters. This saves code, and it is reasonable that the inner class result object is fully exposed to its parent command object.
  11. In the case of a command list, its result object contains a list of the results for its constituent commands, stored in the same sequence as the original command list.
  12. Each command, when inserted into the list, has its own internal listIndex property which stores its position in the list. After the command list has been executed, a fetch method is called on the returned result command list. The original command(s) stored in the list are passed to the fetch method. The fetch method uses the listIndex property from each command to fetch its results, as the results are stored in a list in the same sequence as the original command list. The result object from the list is then polymorphically assigned to the result property of the object passed in to the fetch method. The beauty of this is that the caller has no knowledge of the list index – they simply pass in the same object that they originally added to the command list when fetching the results, and this object holds its index in the list. This avoids errors which could easily occur if list indexes were explicitly hard coded. Refactoring for example could change the indexes of existing commands and break the code, which is completely avoided with this mechanism. Also, as the results are passed back into the original object, the original object may then be used to access the contents of the results as it knows the exact type of the results class – the results are its own! In this way, the results may be fetched polymorphically but accessed via the correct subclass.  At present, the error handling in the example is incomplete. Ideally a type check should be performed in fetch to confirm that the class passed into fetch really is an instance of the same type as the one in the command list. (If this is not the case, run time errors will happen when the result object is accessed as it will be the wrong result subclass.) One reason it may not be could be if the caller passes in a command object which was added to a different list, i.e. the command object is not for the list that is being accessed. A command object can be reused across multiple command lists, but can only be used with a new list after the results have been fetched into it (and accessed) from the list it was last added to and executed in. Another problem could arise if a caller passed a new instance of a command object into fetch – this would have a null listIndex and would therefore give an error. Error handling could also be improved by having a unique ID assigned to each command list, and storing this ID in each command object as well as the list Index. Then the fetch method could check this ID for a match as well. The ID could be reset if the command list is cleared for reuse a subsequent time. This kind of error cannot be detected at compile time with Generics as the list contains a mix of different Command subclasses. The polymorphic casting/assignment of the result object does not give any unchecked warning errors as Generics have not been used here. (Even with Java 5 and later, you won’t necessarily get unchecked warnings when you are using your own non-generic classes.)
  13. If an anonymous inner class is used as an initialiser, the anonymous inner class has access to the properties of its creator, i.e. the client object creating and invoking the commands. In particular, it can access the command object references which have been added to the command list. An initialiser is passed both the original command list and the results so far up to the point reached in the list. It can then use the standard fetch method on one of the object references added to the list in order to fetch details of previous results in the list, and use them to initialise the passed parameters for the command it is initialising (or indeed a later one in the list if required). Note that an anonymous inner class can only access final objects in its parent/creator, so this means that in this case any commands added to the list which are referenced in this way must be declared final. This is not the problem it might seem – for a final object, only the object reference cannot change – properties of the object can still be modified. Note that as CDI is normally used to inject all the object references, CDI constructor injection must be used to inject these object references in order to allow them to be final but still injectable by CDI. This is very straightforward (see the example code)– just define a constructor with all the required final objects as parameters, assign them in the constructor, and prefix the constructor with @Inject.
  14. Each initialiser returns a boolean. If true, the command and subsequent ones are executed normally. If an initialiser returns false, then all command execution is aborted at that point, and the results of any commands not executed are set to null. This would be convenient for example where subsequent commands depend on the result of an initial one, and the initial one returns null – the whole sequence can then be aborted as there is no point in executing all the dependant commands – they will all also return null.
  15. Each command has an enabled property which defaults to true. An initialiser can use this to disable any subsequent commands in the list (while leaving others enabled), as each initialiser is passed the original command list as well as the results so far. An initialiser is also passed the index of its own command in the command list so it is fully aware of the point reached in the list.

No Comments »

December 12th, 2010
7:37 pm
Using the Enterprise Architect UML design tool

Posted under UML
Tags , , , , ,

Updated 11/12/2010

I’ve clarified some of the points re collection classes, code generation, and the Local Path feature.

 

Original Post (7/5/2010, 07:30)

I’m trialling Enterprise Architect from Sparx Systems at the moment, and have found the following points/tips/gotchas so far :-

Class Stereotypes

If you choose a stereotype such as entity which has its own image, this changes the appearance on the class diagram and prevents detail such asproperties and operations being listed. You can either use another stereotype (or none at all – sometimes I have not as it clutters up the simplicity of the diagram), or you can customise the appearance under settings/uml to prevent the image being used.

Collection classes and generics for relationships

The collection class to be used can be set as a global default or per class:-

  • global default – visit Tools/Options, pick Java under source code engineering in the left hand treeview pane. Click the Collection Classes button to configure the defaults. Note that you can enable generics by using e.g. Collection<#TYPE#> as the definition, where #TYPE# is replaced by the appropriate class name. This is mentioned in the help but is not easy to dig up. You can set different collection classes for Default, Ordered, and Qualified.
  • Per Class setting – open the class details (double click on the class), select the details tab, and click the Collection Classes button to configure the class in the same way as with the global defaults (including generics using #TYPE#). **Important potential Gotcha** – when setting this up, it is easy to get confused. If Class A contains a collection of Class B, then to enable a collection declaration to appear in the Java code for Class A, you must set the appropriate collection class settings on Class B, not Class A. Setting up class B will then cause that declaration to appear in Class A. Note that the per class settings overide any global default that you have applied.
  • The trigger for generation of the collection declaration is to set the Multiplicity at the appropriate end of the (aggregation) relationship between the classes. So for example, an Application might have a 0-or-1 to many relationship with AppRole, i.e. an Application will hold a collection of AppRoles. The aggregation relationship will be drawn from the AppRole class to  the Application class, such that the diamond arrowhead appears against the Application class, as that holds the collection. You would then double click the relationship, and under Source Role you would set a Multiplicity of 0..*, and under the Target Role you would set a multiplicity of 0..1. This will cause the collection declaration when the code is generated. Note that there are other settings on the source and target role pages for Role and alias, and derived, derived union, and owned. These do not appear to affect the code generation (at least in my simple examples).
  • Note that if you select ordered on the multiplicity you get the ordered type of collection class. In my case, I used global settings of Collection for unordered, List for ordered, and left the qualified as Collection. Using this I obtained a declaration of List in the generated code when I selected ordered on the multiplicity of the 0..* end of the relationship (Source Role in the above example).

Enabling/Disabling Destructor (Java finalize) calls

These can also be configured globally or on a per class basis :-

  • Global default – visit Tools/Options, pick Object Lifetimes under source code engineering, and tick or untick generate destructor. Constructors can be similarly configured.
  • Per Class setting – right click on the class and select Generate Code. Click advanced, and the same page is displayed as for the global default. Constructors/destructors are configured in the same way as above, except that the settings are per class rather than global defaults.

When Java is the target language, enabling a destructor adds a call to finalize as Java is garbage collected and does not have explicit destructors. finalize is called by the garbage collector to notify the object of garbage collection, but the call is made at the discretion of the garbage collector. For Java you would normally want to untick the generate destructor  setting.

Auto generation of package statements in Java

To configure this, you select a package in the project browser hierarchy as the package route, by selecting Code Engineering on its context menu, then picking Set as Namespace Root. Then, all packages under that root package (but not including the root package) will have their names contatenated to form the java package that is used in the code. You can use dots in the package name, so for example you could have a package heirachy of Class Model/uk.co.salientsoft/appname/domain, where Class Model would be set as the root. Then, classes in the Domain package would have a package in the code of uk.co.salientsoft.appname.domain as you would expect. Note that there are some gotchas/possible bugs around this. I only managed to get it to work when I actually created a class diagram at each level and added the next sub package onto the diagram. This looks tidy/correct anyway, and is what the example does, but it is not enforced – you can have a package hierarchy in the browser without having all the intervening class diagrams with the next subpackage on, but if you do so, it appears that package statements are not then output in the java code.

Code generation / directories

When generating code, this can be done at package level by selecting Code Engineering/Generate Source Code from a package context menu in the project browser. Ticking Include All Child Packages does just that and generates the code recursively down the package tree. You can select Auto generate files to cause the file directory paths to be automatically derived from the package hierarchy, ignoring any path set for the individual classes. However, I found this awkward to set up – ideally I wanted a java directory tree to match the package fields, but to do this seems to need a carefully crafted package hierarchy which may not match the way you want to work. For example, I had a package called uk.co.salientsoft, which ended up as a single directory name rather than being broken down into component fields. I did not want to add all the individual package levels for uk, co, and salientsoft. Also, when you Auto generate files the root path under which the tree is created is not saved and you have to browse for it every time – not pleasant. Therefore, in the end I elected not to use Auto generated files, but to set the correct file path on each class. Thus can be done by right clicking the class and selecting Generate Code, then browsing for the desired path. Clicking Save will save the path which is then used for code generation as above. Having done this, I finally acheived correct package statements in the code together with the correct directory hierarchy.

Using Local Paths

Local Paths offer a means of parameterising root directories e.g. for code generation, such that the same EAP  file can be used by multiple users with different local code generation directories.

On the surface it looks like a means of defining environment/path style variables within EA, which you then use when defining code generation locations. This is somewhat of a misconception, which is unfortunately reinforced by the section of the help on Local Paths:-

Developer A might define a local path of:
JAVA_SOURCE = “C:\Java\Source”

All Classes generated and stored in the Enterprise Architect project are stored as:
%JAVA_SOURCE%\<xxx.java>.

Developer B now defines a local path as:
JAVA_SOURCE =”D:\Source”.

Now, Enterprise Architect stores all java files in these directories as:
%JAVA_SOURCE%\<filename>

On each developer’s machine, the filename is expanded to the correct local version.

In fact, whilst you do define a local path under Settings/Local Paths…  and give the local path an ID (or variable name), you do not enter the ID anywhere when configuring directories for code generation – the local paths are applied behind the scenes in somewhat of a smoke and mirrors fashion.  In fact you do the following to set it up (example is for setting Java code generation directories directly on classes) :-

  • Select Code Generation… on the context menu for one or more classes on a class diagram. Browse for the actual desired full path for the class. You will note that at no stage is there a means to enter a variable ID in the path – you are just using the standard file browse dialog.
  • Under Settings/Local Paths… create a local path of type Java, browsing to a root directory which is either the path entered for the classes or a parent directory on the same path. Save it with a suitable name.
  • Clicking Apply Path will then apply the path to the code generation directories. It will return a count of the number of instances it applied (number of paths found). In my case, it initially found 0, but when I clicked Expand Path which reverses the process and removes your local path, and is supposed to revert to using normal full directories again – it said it removed 4 (the number of affected classes). When I clicked Apply Path again, it again found all 4, so I suspect the initial “found 0” was a bug and it had worked – confusing, especially as it is all doing stuff behind the scenes!
  • Now, to see the effect of what you have done, change your local path definition in the local path dialog for the ID you created and applied, and save the change. Now look at the code generation folders for the classes again under Code Generation…  on the context menus for the classes, and you should find that the path has changed by magic to the one you just set in the Local Path dialog! Smoke and mirrors indeed.
  • Note that normally your local path definition will just be a parent directory which is shared by all your code generation subdirectories for the classes, as there will typically be a number of different subdirectories. EA correctly changes just the parent directory part of the path.
  • You can then if desired define a number of local paths for Java, e.g. “Freds path”, “Bills path”, and apply the desired one which will then take effect. You will not see any local path IDs appearing anywhere, they are stored in the path but applied behind the scenes.
  • To switch between local paths again feels strange. You would expect that if “”Freds path” is in effect and you apply “Bills path” (which has a different definition), then the directories will  all change. They do not! What you have to do is to define “Bills path” initially to be the same definition as “Freds path”, then do an Expand Path for “Freds Path” (Whereupon you will see the correct count of classes affected). Then you can do an Apply Path for “Bills path”, which will then be applied to the same number of classes. Finally, you can amend “Bill’s path”, which is the one that currently has control, and all the class code generation directories will change.
  • One frustration of this method is that when adding new classes when a local path is in effect, you must still browse to the correct actual directory just as you would if no local path was present – you cannot enter the local path anywhere. It will however take effect ‘by magic’. In my case, I created a new class under the local path, and it immediately ‘took on’ the local path and would change its directory when I changed the local path definition, even though I had not done an ‘Apply Path’ to pick up the new class.
  • It appears therefore that new classes under the parent folder of a currently active local path pick up the effect of the local path by default.

 

My scenario is not the actual use case which will occur in practice, as I was doing this as a single user and making changes. In practice, if the EAP file was passed around, a different user would already have his source directories created according to his own standard. Nevertheless, I find the operation of this functionality to be strange, counterintuitive, and even slightly buggy in parts.

Having said that, in fairness, EA is the best UML tool I tested by far in my price range as an independent developer – $199 for the professional edition, as opposed to a 4 figure sum for other packages which I did not even bother to look at. The other features of EA are very fully functional, intuitive to use and bug free. Surprisingly, as per my other post here, all the other packages I looked at were very poor in comparison, so for my needs and price range,  and from my testing, it is still very much a one horse race.

No Comments »

December 10th, 2010
9:59 am
Date, time and calendar handing in Java

Posted under Java
Tags , , , , ,

This is rather a minefield for the unwary, and in general the various APIs in this area come in for a fair share of criticism.
Poor design, leaky abstractions and unhelpful idioms are variously cited.
However, the functionality available is comprehensive even though it can be tricky to use.

The following posts offer good advice in finding your way!

David Jenkov’s Java Date and Time Tutorial – an excellent tutorial with a number of articles on date, time, calendar handling etc.

O’Reilly OnJava.com – Making Sense of Java’s Dates – another very good tutorial

Sun Java Tutorials – Dates and Times – Sun’s Java tutorial on dates & times

Lavnish – Java Calendar vs Date – article on Lavnish’s blog

No Comments »

December 3rd, 2010
12:17 pm
Using the Primefaces Breadcrumb Component

Posted under JSF
Tags , , , ,

I did some experimentation on the best look and feel (in my humble opinion!) for this component, and found the following points along the way:-

  • By default the component was underlining all the entries. This was because all anchor tags were being underlined. The Primefaces showcase has specific rules in default.css to turn this off, so I added them too. (You might have expected this to all be done by the themes or breadcrumb css, but not the case). I just added “a {text-decoration: none;}” and “a:hover {text-decoration: underline;}” rules, but obviously there are other ways if you want other links to be underlined.
  • I then tried to place a breadcrumb in a scrolling div, to ensure that it would still work if the content overflowed. I knew that horizontal scroll bars on a breadcrumb would not look at all sexy, but wanted at least some solution for edge cases with extreme amounts of content, as by default the component truncates to the right and content is lost/not accessible. I was unable to solve this issue – the component would not play ball. I wanted to leave an inner div containing the component at a floating size, so that the control sized itself for the content, and then add a scrollable outer div with overflow:auto so that it would scroll if needed. However, the component appears to use some jQuery magic to detect the size of any fixed ancestor outer level div of the component, and then fix the control width to that size using inline styling added to one of its own inner divs by jQuery/Javascript. The only partial solution was to have a large fixed size component in a smaller outer scrolling div, but this was not good as the scrollbars were present even if not needed as the control had a fixed size.
  • The problem could probably be solved using jQuery, perhaps by modifying the jBreadcrumb jQuery component which Primefaces uses, but I did not investigate this further.
  • In the end, I reconciled myself with the default way the component works. It does have a good solution to this issue by (optionally) dynamically collapsing the entries to a designated preview width, and then expanding an entry on mouse hover (so-called preview mode). This does save a lot of space, and I decided that I could easily have more than enough entries for my needs in say an 800 pixel wide breadcrumb. Alternatively the component can be left to float entirely and rely on the browser for scrolling, but in practice there will generally be an outer container of some kind which will set a limit and trigger the above issue. In my case, this would likely be an outer level tab for a form.
  • I also decided that in practice it would be helpful to turn the preview mode on dynamically, perhaps say when the number of entries exceeded a certain number, or better still when the total character count in the breadcrumb exceeds a certain figure, as this would give good results on average and still be easy to calculate. For normal use, when there is plenty of room left in the breadcrumb, preview mode is a nuisance, but it is obviously essential when the component fills up. Ideally, this would be done when the component is filled rather than based on an entry count, but this would be tricky to calculate. Ideally this would be done dynamically by the component itself. Best of all might be a dynamic preview mode which shrinks the entries only when required and only enough to fit everything in the component.
  • Rendering the component in preview mode takes significant time when there are a lot of entries (even on my Core I7 920). This might be an issue when partially updating a page (and the component) during navigation. This is even more reason not to use preview mode unless it is really essential, as with it turned off the breadcrumb renders very quickly. On some occasions it would be possible to update the control client side, for example when just changing the underline/italic decoration on the text (see below re traversing a hierarchy) and no entries are added or removed. In this case the necessary classes could just be added and removed from the breadcrumb entries dynamically with jQuery. I have also not tried any Ajax/partial form updates with it, for example just adding or removing a single entry, but I expect the whole component will be re-rendered each time as the manual makes no mention of partial updating.
  • I experimented a bit with the expand and contract timings in preview mode. These interact with the time taken by the JavaScript to dynamically collapse the entries when the component is first rendered, so if you try to make them too fast it looks clunky. Also if the expand is too fast it can confuse you as to which entry you are hovering on, especially when there is a lot of preview compression, as you can end up highlighting the next entry along without realising it, just due to the expand/collapse effect.
  • One common use case for me is to use the component to hold the navigation path when traversing a hierarchical data set. A desirable feature would be that when you traverse back up the tree say by clicking on one of the higher levels in the breadcrumb, you do not immediately lose all the lower levels you visited. They would only be removed if you visited a higher level and then traversed down a different lower level path at some point, in which case the lower levels visited previously beyond that point would then be removed and a new path built.
  • The nice thing about the above concept is that you can repeatedly wander freely up and down a given tree path via the breadcrumb without losing any of the context, which is handy in my case as the UI deliberately only shows the current level of the tree in a table – no tree or treetable components are used in order to keep things intuitive and simple for novice users.
  • When applying this concept, it is necessary to highlight the current location in the breadcrumb, as this will no longer always be the rightmost entry. The most logical way to do this seemed to apply the same highlight as the mouse hover, which is to underline an entry. Therefore, the current entry will always be underlined, as will any other entry that is hovered over.
  • In addition, it is desirable to distinguish between the breadcrumb levels between the root and the current point from those previously visited below the current point, as the breadcrumb is no longer only showing the path to where you currently are. I tried various kinds of dimmed, disable style highlighting, but whilst it is important to make these previously visited lower level entries look different, it must also be clear that you can still click on them. In the end, my preferred solution which looks good in all the top 5 browsers and with all the Primefaces themes was to italicise the previously visited lower level entries. You therefore end up with ‘normal’ styling up to the current level. The current level itself is then shown underlined so it is clear where you are. All the entries to the right (if any) are then italicised.

The following example shows my preferred component, which is somewhat thinner than the default due to the removed padding. Examples of the different highlighting discussed above are all just coded directly into the menu options. The example also uses my theme switcher component which is not listed.

 

index.xhtml

<!DOCTYPE HTML>
<html xmlns="http://www.w3c.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:fn="http://java.sun.com/jsp/jstl/functions"
xmlns:p="http://primefaces.prime.com.tr/ui"
xmlns:c="http://java.sun.com/jsp/jstl/core"   
xmlns:util="http://java.sun.com/jsf/composite/uk.co.salientsoft/util">
<f:view contentType="text/html">
<h:head>
    <util:themeSwitcher    outputStyle="true"
                        themeBase="/resources/themes"
                        defaultTheme="redmond"/>
<style>
    .ui-widget {
        font-size: 75% !important;
    }
    h1.header {
        font-size: 1.2em !important;
        padding: 5px;
        margin: 0px 0px 20px 0px;
        float: left;
    }
    .themeswitcher {
        float: left;
        clear: both;
        margin-bottom: 20px;
    }   
    .ss-breadcrumb {
        clear:both;
        margin: 0 0 10px 0;
        padding: 0;
        width:800;
    }   
    a {text-decoration: none;}
    a:hover {text-decoration: underline;}
    .ss-currentlevel {text-decoration:underline;}
    .ss-lowerlevel {font-style: italic;}
</style>

</h:head>
<h:body>
<h1 class="header ui-widget ui-widget-header ui-corner-all" style="">Breadcrumb</h1>

<h:form id="frmTest">
<util:themeSwitcher form="frmTest" outerStyleClass="themeswitcher"/>
<br/><br/>
    <p:breadCrumb styleClass="ss-breadcrumb" preview="false">
        <p:menuitem value="Categories" url="#" />
        <p:menuitem value="Sports" url="#" />
        <p:menuitem value="Football" url="#" />
        <p:menuitem value="Countries" url="#" styleClass="ss-currentlevel"/>
        <p:menuitem value="Spain" url="#"  styleClass="ss-lowerlevel"/>
        <p:menuitem value="F.C. Barcelona" url="#" styleClass="ss-lowerlevel"/>
        <p:menuitem value="Squad" url="#" styleClass="ss-lowerlevel"/>
        <p:menuitem value="Lionel Messi" url="#" styleClass="ss-lowerlevel"/>
        <p:menuitem value="Squad" url="#" styleClass="ss-lowerlevel"/>
        <p:menuitem value="Lionel Messi" url="#" styleClass="ss-lowerlevel" />
    </p:breadCrumb>
    <p:breadCrumb styleClass="ss-breadcrumb" preview="true" previewWidth="24"
        expandEffectDuration="400" initialCollapseEffectDuration="100"
        expandedBeginningItems="1" expandedEndItems="1">
        <p:menuitem value="Categories" url="#" />
        <p:menuitem value="Sports" url="#" />
        <p:menuitem value="Football" url="#" />
        <p:menuitem value="Countries" url="#" />
        <p:menuitem value="Spain" url="#" />
        <p:menuitem value="F.C. Barcelona" url="#"  styleClass="ss-currentlevel"/>
        <p:menuitem value="Squad" url="#" styleClass="ss-lowerlevel" />
        <p:menuitem value="Lionel Messi" url="#" styleClass="ss-lowerlevel" />
        <p:menuitem value="Categories" url="#" styleClass="ss-lowerlevel" />
        <p:menuitem value="Sports" url="#" styleClass="ss-lowerlevel" />
        <p:menuitem value="Football" url="#" styleClass="ss-lowerlevel" />
        <p:menuitem value="Countries" url="#" styleClass="ss-lowerlevel" />
        <p:menuitem value="Spain" url="#" styleClass="ss-lowerlevel" />
        <p:menuitem value="F.C. Barcelona" url="#" styleClass="ss-lowerlevel" />
        <p:menuitem value="Squad" url="#" styleClass="ss-lowerlevel" />
        <p:menuitem value="Lionel Messi" url="#"  styleClass="ss-lowerlevel" />
    </p:breadCrumb>
</h:form>
</h:body>
</f:view>
</html>

No Comments »

November 30th, 2010
4:37 pm
Tailoring a Primefaces TreeTable with JavaScript/jQuery/JSF 2.0

Posted under JSF
Tags , , , , , , , ,

This example came about from the desire to hightlight a Primefaces TreeTable row when a checkbox in the row is ticked. I wanted to do this because a ticked checkbox is not as visible as I would like when a lot of data is present. I was not keen on adding DataTable style dynamic selection by hovering and clicking anywhere in a row, as this conflicts somewhat with the paradigm of clicking on the expander to expand/collapse the tree, and you would have to special case hovering/clicking on the expander somehow to prevent row selection.

Ideally you would use CSS for this, but this would involve tagging a component in a TreeTable cell (<td> element) with a class (as in the TreeTable component we cannot directly add row styling), and then using some kind of ancestor selector to traverse the DOM tree upwards to get the row. The simple answer to this is that whilst CSS can do some clever things, it does not have any kind of ancestor selector, so it is not possible to do it just with CSS.

An attractive alternative for this kind of thing in Primefaces is to use jQuery – a very powerful JavaScript based UI library upon which Primefaces is based. As it is already present in a Primefaces environment, it is trivial to call and ideal for this kind of thing. In particular, it has powerful mechanisms for traversing and searching the DOM tree and selecting elements etc. If you combine this with its features for dynamically adding and removing classes from elements, it can do exactly the kind of thing that we cannot do in CSS. The jQuery website is here, and the API documentation for it may be found here.

The sample code fragments below demonstrate the idea. The sample is based on a hacked version of the the Primefaces showcase TreeTable demo. Note the following points:-

  • It is perfectly possible to add both Javascript and JSF EL inline inside a JSF component, such that the JavaScript runs at that point when the page is rendered. This example adds some JavaScript inside the JSF tags for a checkbox.
  • As the example uses JavaScript, the hightlight is added/removed both client side from a click event on the check box, and when the page is rendered based on the current check box value in the TreeTableDocument object from the server.
  • The sample uses the JSF 2.0 EL implicit object reference component.clientId to get the client ID of the component where the EL reference is used. This is new for JSF 2.0 (previously additional code would be needed for this) and like the cc implicit object used with composite components, is not at all well documented. I was unable to find reference documentation for it anywhere in the JSF 2.0 specs, but found details of it here (at the end of the post). Note that the reference needs to be placed with care – it sometimes appears to come up with ‘ghost’ client IDs which may have been allocated by JSF but do not actually appear anywhere as IDs in the HTML. When using it, check that it returns the correct ID, for example by just placing a bare #{component.clientId} on the page directly adjacent to where you are using it, and view the source of the generated page in the browser to check that the client ID it returns matches the id of the component it is used for.
  • Be careful to consider any ordering issues – the inline JavaScript call I am using must be placed on the page after the component it refers to has been rendered. By default, using component.clientId  inside a script block which is in turn inside the checkbox component tags causes the script block to be output immediately prior to the html for the checkbox. Therefore, I use two script blocks – one inside the checkbox to save the component ID in a temporary JavaScript variable, which guarantees that I obtain the correct component ID and not an incorrect or ‘ghost’ one, and then another script block immediately after the closing tag for the checkbox component which passes the form ID and saved component ID to a JavaScript function which calls jQuery to do the highlighting after the html element has been rendered on the page. Note that the client side onClick() event on the checkbox will always run after  the full page has been rendered, when the user clicks the box, so ordering is not an issue for this.
  • The call to jQuery passes in the checkbox DOM element, which jQuery wraps with a jQuery object and returns. The parent() method is then used twice to traverse the DOM tree up from the check box to the table cell <td>, and thence to the table row <tr>. The addClass() and removeClass() methods are then used to dynamically add/remove the required CSS classes to the table row depending on the passed check box state. Adding and removing classes with jQuery is useful as it does all the string bashing for you to check if the class being added/removed is already present, handles spaces correctly, and leaves all other classes on the element intact.
  • Note that in an earlier version I had tricky issues with nested quotes in JSF EL. I initially used outer double quotes, with inner single quotes on the JavaScript calls. The EL through this out however. I ended up using double quotes throughout, and escaped the inner ones with backslashes (\). This worked fine. The version shown here does not need this as it is a later modification.
  • The example extends the Primefaces Document class used in the showcase, adding a boolean property for the check box value.
  • My example uses CDI, whereas the original showcase uses JSF managed beans.

Sample Code Fragments

Index.xhtml

<!DOCTYPE HTML>
<html xmlns="http://www.w3c.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:fn="http://java.sun.com/jsp/jstl/functions"
xmlns:p="http://primefaces.prime.com.tr/ui"
xmlns:c="http://java.sun.com/jsp/jstl/core"   
xmlns:util="http://java.sun.com/jsf/composite/uk.co.salientsoft/util">
<f:view contentType="text/html">
<h:head>
    <util:themeSwitcher    outputStyle="true"
                        themeBase="/resources/themes"
                        defaultTheme="redmond"/>
<style>
    .ui-widget {
        font-size: 75% !important;
    }
    h1.header {
        font-size: 1.2em !important;
        padding: 5px;
        margin: 0px 0px 20px 0px;
    }
    h2.subheader {
        font-size: 0.9em !important;
        padding: 2px;
        margin: 0px 0px 10px 0px;
    }
    .float {
        float: left;
    }
   
    .clear {
        clear: both;
    }
    .themeswitcher {
        float: left;
        clear: both;
        margin-bottom: 10px;
    }   
    .ss-selectcolumn {
        width:30px !important;
        padding:0px !important;
        text-align:center;
    }
    .ss-checkbox {
        color:red!important;
    }
/* treetable arrow light/dark switch
    .ui-treetable tr.collapsed td .expander {
        background-image:url("/TreeTable1/javax.faces.resource/treetable/images/toggle-expand-light.png.jsf?ln=primefaces&amp;v=2.2.RC2");
    }
    .ui-treetable tr.expanded td .expander {
        background-image:url("/TreeTable1/javax.faces.resource/treetable/images/toggle-collapse-dark.png.jsf?ln=primefaces&amp;v=2.2.RC2");
    }   
*/
/* Styling nicked from default.css in the Primefaces Showcase */
    a {text-decoration: none;}
    a:hover {text-decoration: underline;}
    a img {border: none;}   
</style>

<script type="text/javascript">
//<![CDATA[
    function highlightTreeTableRow(formId, checkBoxId) {
        var checkBox = document.forms[formId][checkBoxId];
        if (checkBox.checked)
            jQuery(checkBox).parent().parent().addClass(‘ui-state-highlight ui-selected’);
        else
            jQuery(checkBox).parent().parent().removeClass(‘ui-state-highlight ui-selected’);
    }
//]]>
</script>
</h:head>
<h:body>
<h1 class="float header ui-widget ui-widget-header ui-corner-all" style="">Theme Switcher</h1>
<h:form prependId="false" id="frmTest">
<util:themeSwitcher form="frmTest" outerStyleClass="themeswitcher" style="margin-bottom:20px;"/>
<br/><br/>

<div style="width:600px;clear:both;">
    <p:treeTable value="#{documentsController.root}" var="document"
       styleClass="#{(document.name==’logo.png’)? ‘ui-state-highlight ui-selected’:’fred’}"
        expanded="true">
        <p:column>
            <f:facet name="header">
                Name
            </f:facet>
            <h:outputText value="#{document.name}" />
        </p:column>
       
        <p:column>
            <f:facet name="header">
                Size
            </f:facet>
            <h:outputText value="#{document.size}" />
        </p:column>
       
        <p:column>
            <f:facet name="header">
                Type
            </f:facet>
            <h:outputText value="#{document.type}" />
        </p:column>
       
        <p:column>
            <f:facet name="header">
                Options
            </f:facet>
            <p:commandLink update="documentPanel" oncomplete="documentDialog.show()" title="View Detail">
                <p:graphicImage value="/images/search.png"/>
                <f:setPropertyActionListener value="#{document}" target="#{documentsController.selectedDocument}" />
            </p:commandLink>
        </p:column>
       
        <p:column styleClass="ss-selectcolumn">
            <f:facet name="header">
            <h:selectBooleanCheckbox disabled="true" label="box header"/>
            </f:facet>
            <h:selectBooleanCheckbox value="#{document.selected}"
                 
onclick="highlightTreeTableRow(‘frmTest’, this.id);" styleClass="ss-checkbox" id="selector" >                
                 <script>selectId = ‘#{component.clientId}’;</script>
            </h:selectBooleanCheckbox>
            <script>highlightTreeTableRow("frmTest", selectId);</script>
        </p:column>
    </p:treeTable>
    <p:commandButton type="submit" value="Submit" onclick="submit();" style="margin-top:10px;"/>
   
    <p:dialog header="Document Detail" fixedCenter="true" effect="FADE" effectDuration="0.3"
        widgetVar="documentDialog" modal="true">
   
        <p:outputPanel id="documentPanel">
            <h:panelGrid  columns="2" cellpadding="5">
                <h:outputLabel for="name" value="Name: " />
                <h:outputText id="name" value="#{documentsController.selectedDocument.name}" style="font-weight:bold" />
               
                <h:outputLabel for="size" value="Size: " />
                <h:outputText id="size" value="#{documentsController.selectedDocument.size}" style="font-weight:bold" />
               
                <h:outputLabel for="type" value="Type " />
                <h:outputText id="type" value="#{documentsController.selectedDocument.type}" style="font-weight:bold" />
            </h:panelGrid>
        </p:outputPanel>
    </p:dialog>
    </div>
</h:form>
</h:body>
</f:view>
</html>

DocumentsController.java (modified from Showcase)

package org.primefaces.examples.view;
import java.io.Serializable;
import java.util.logging.Logger;
import javax.enterprise.context.SessionScoped;
import javax.inject.Named;
import org.primefaces.model.DefaultTreeNode;
import org.primefaces.model.TreeNode;
import uk.co.salientsoft.treetable.view.TreeTableDocument;

@Named
@SessionScoped
public class DocumentsController implements Serializable {
   
    private static final long serialVersionUID = -3593168523028092346L;
    private static final Logger logger = Logger.getLogger(DocumentsController.class.getName());
    private TreeNode root;
    private TreeTableDocument selectedDocument;
    public DocumentsController() {
        root = new DefaultTreeNode("root", null);
       
        TreeNode documents = new DefaultTreeNode(new TreeTableDocument("Documents", "-", "Folder"), root);
        TreeNode pictures = new DefaultTreeNode(new TreeTableDocument("Pictures", "-", "Folder"), root);
        TreeNode music = new DefaultTreeNode(new TreeTableDocument("Music", "-", "Folder"), root);
       
        TreeNode work = new DefaultTreeNode(new TreeTableDocument("Work", "-", "Folder"), documents);
        TreeNode primefaces = new DefaultTreeNode(new TreeTableDocument("PrimeFaces", "-", "Folder"), documents);
       
        //Documents
        TreeNode expenses = new DefaultTreeNode("document", new TreeTableDocument("Expenses.doc", "30 KB", "Word Document"), work);
        TreeNode resume = new DefaultTreeNode("document", new TreeTableDocument("Resume.doc", "10 KB", "Word Document"), work);
        TreeNode refdoc = new DefaultTreeNode("document", new TreeTableDocument("RefDoc.pages", "40 KB", "Pages Document"), primefaces);
       
        //Pictures
        TreeNode barca = new DefaultTreeNode("picture", new TreeTableDocument("barcelona.jpg", "30 KB", "JPEG Image"), pictures);
        TreeNode primelogo = new DefaultTreeNode("picture", new TreeTableDocument("logo.jpg", "45 KB", "JPEG Image"), pictures);
        TreeNode optimus = new DefaultTreeNode("picture", new TreeTableDocument("optimusprime.png", "96 KB", "PNG Image"), pictures);
       
        //Music
        TreeNode turkish = new DefaultTreeNode(new TreeTableDocument("Turkish", "-", "Folder"), music);
       
        TreeNode cemKaraca = new DefaultTreeNode(new TreeTableDocument("Cem Karaca", "-", "Folder"), turkish);
        TreeNode erkinKoray = new DefaultTreeNode(new TreeTableDocument("Erkin Koray", "-", "Folder"), turkish);
        TreeNode mogollar = new DefaultTreeNode(new TreeTableDocument("Mogollar", "-", "Folder"), turkish);
       
        TreeNode nemalacak = new DefaultTreeNode("mp3", new TreeTableDocument("Nem Alacak Felek Benim", "1500 KB", "Audio File"), cemKaraca);
        TreeNode resimdeki = new DefaultTreeNode("mp3", new TreeTableDocument("Resimdeki Gozyaslari", "2400 KB", "Audio File"), cemKaraca);
       
        TreeNode copculer = new DefaultTreeNode("mp3", new TreeTableDocument("Copculer", "2351 KB", "Audio File"), erkinKoray);
        TreeNode oylebirgecer = new DefaultTreeNode("mp3", new TreeTableDocument("Oyle bir Gecer", "1794 KB", "Audio File"), erkinKoray);
       
        TreeNode toprakana = new DefaultTreeNode("mp3", new TreeTableDocument("Toprak Ana", "1536 KB", "Audio File"), mogollar);
        TreeNode bisiyapmali = new DefaultTreeNode("mp3", new TreeTableDocument("Bisi Yapmali", "2730 KB", "Audio File"), mogollar);
    }
    public TreeNode getRoot() {return root;}
    public void setRoot(TreeNode root) {this.root = root;}
    public TreeTableDocument getSelectedDocument() {return selectedDocument;}
    public void setSelectedDocument(TreeTableDocument selectedDocument) {
        this.selectedDocument = selectedDocument;
    }
}

TreeTableDocument.java

package uk.co.salientsoft.treetable.view;
import org.primefaces.examples.domain.Document;

public class TreeTableDocument extends Document {
    private static final long serialVersionUID = 7339615098050125785L;
    public TreeTableDocument(String name, String size, String type) {
        super(name, size, type);
    }   
    private boolean;
    public boolean isSelected() {return this.selected;}
    public void setSelected(boolean selected) {this.selected = selected;}
}

No Comments »