Archive for the 'Glassfish' Category

October 4th, 2011
12:10 pm
Glassfish 3.0.1–Slow login due to checking for updates

Posted under Glassfish
Tags , ,

I did a new install of GF 3.0.1 on a laptop, and elected not to install the update tool as this was a fixed demo environment.

I found that when connecting to Glassfish admin, login was very slow, easily taking a minute or more longer than normal. After login, the main screen displayed a count of available updates at the top left, which I had not seen in the past. This looked suspicious and I wondered if the slowness was due to checking for available updates.

It turned out that this was indeed the case. This post discusses the issue and various workarounds, including disabling network access for Glassfish and removing a jar – neither of which I particularly liked. The post indicated that you could set preferences in the update tool, but as I had not installed it I was stuck.

I then tried reinstalling GF from scratch, this time selecting the update tool as well during install, but not selecting the check box for ‘checking for updates’. After doing this, I discovered that the problem was no longer present – login was quicker and the count of available updates was not displayed. It was also possible to use the update tool to configure preferences, but in my case automatic update checking was off anyway.

The solution to this issue, somewhat paradoxically, is therefore, if you want a fixed installation with no update checking, make sure you still select the update tool when installing, but do not enable checking for updates. This solves the problem, and also allows you to configure update preferences later if you wish.

No Comments »

April 2nd, 2011
5:50 pm
Updating components such as JSF, JPA in Glassfish

Posted under Glassfish
Tags , , , , ,

Update 04/10/2011

An essential step was omitted below, which is to clear out the OSGI cache. If you do not do this, and for example manually update Mojarra, the old version will still be loaded from the OSGI cache so your update will not take effect (and probably leave you wondering where glassfish can possibly still be getting the old version from!)

The simple solution is to ensure that you clear the OSGI cache after an update. The cache will be automatically rebuilt by Glassfish.

Simply delete all files in the  <glassfish-root>/glassfish/domains/domain1/osgi-cache/ folder. (Typically this just has a felix  subfolder to be deleted).

This solves the problem.

 

Original

Glassfish has its updatetool which automatically lists and installs updates from known repositories. You can add to the list of repositories, but they have to be of the type that Glassfish will accept – it will not install from any old download site.

When I wanted to update Mojarra in GF 3.0.1 from 2.0.2 FCS to 2.0.4 FCS with the updatetool, I could not find an update site with that version on.

The alternative (which I did) is to update manually – in this case to stop Glassfish and copy the jsf-api.jar and jsf-impl.jar into the <glassfish-root>\glassfish\modules directory, then restart. The only issue with this is that the new version will not be correctly listed in the installed components under the update tool or in the glassfish administration if you do it manually. However, you can verify that the correct version is running by starting glassfish and one of your web apps running in it, then look in the log for Mojarra and you will see that Mojarra logs its version when it loads. (Be careful if using Notepad++ – I found that its search was unreliable when searching backwards in the log for Mojarra, and it missed the relevant matches.

This can also be done for JPA/Eclipselink. However, the issue with this is that in the update tool it is listed with the name Glassfish JPA, with a different version number to the one used for Eclipselink. It is therefore not possible to work out which version of Eclipselink you are upgrading to. Some of the forums suggest just copying in a later set of Eclipselink OSGI jars but this just does not feel right for OSGI!

The only think I can be certain of is the installed version of Eclipselink with a base version of Glassfish, as this is documented as part of the Glassfish release.

At present I am sticking with the Eclipselink 2.0.2 version that ships with Glassfish, as I have not had any problems with this.

No Comments »

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 »

September 19th, 2010
8:46 pm
Servlet Mapping Issues with Glassfish V3.0.1

Posted under Glassfish
Tags , , , ,

There seem to be some servlet mapping issues with Glassfish V3.0.1.

To summarize, the following outlines what the servlet mapping logic should do:-

  1. The <url-pattern> as below matches the input url and if there is a match, passes the url to the designated servlet (in this case the faces servlet).
  2. The url parts that match are stripped out, so that for extension mapping e.g. “*.jsf” pattern the “.jsf” is removed, and for path mapping e.g. “/faces/*” pattern the /faces subdirectory is removed.
  3. The javax.faces.DEFAULT_SUFFIX as below is applied to the result as a file type if one is not present, to give an actual file to be searched for. This is passed to the faces servlet for processing.

I tried the same combination in web.xml that I had used previously on Glassfish V2.1 with ICEfaces:-

<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.jsf</url-pattern>
</servlet-mapping>
<context-param>
<param-name>javax.faces.DEFAULT_SUFFIX</param-name>
<param-value>.jsf</param-value>
</context-param>

The actual file type was also .jsf (index.jsf in this case)
This gave rise to the following intermittent error when run – it would run once or twice and then blow up:-

url:  http://localhost/PrimeTest1/index.jsf
error:  javax.servlet.ServletException: PWC1232: Exceeded maximum depth for nested request dispatches: 20

Changing the actual file type and the above javax.faces.DEFAULT_SUFFIX value to .xhtml worked correctly in every case.
This error occurred both with a simple Primefaces test page:-

<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:p=’http://primefaces.prime.com.tr/ui’>
<h:head> </h:head>
<h:body>
<p:editor />
</h:body>
</html>

and also with a simple JSF page in a non Primefaces JSF 2 faceted eclipse web project:-

<html xmlns=”http://www.w3.org/1999/xhtml”>
<head>
<title>Test Page Title</title>
</head>
<body>
Test page body
</body>
</html>

It was therefore clear that the error was not Primefaces related, but appeared to be recursion caused by a servlet mapping issue. This post on the Glassfish Forums reported the issue – there was some discussion but no resolution, and I don’t think a bug has been raised.  This post also reported the same issue. Whilst I found a number of other posts too with what seemed like a related issue, there appeared to be no clear conclusion on any of them re the nature of the problem or a fix for it. I tried other combinations such as path mapping using “/faces/*” for the url pattern, “.jsf” for the default suffix, and “http://localhost/PrimeTest1/faces/index.jsf” for the url, but in this case the above error did not occur but a blank page was displayed. On examining the source for the page, it turned out to be the original page source i.e. it had not passed through the faces servlet.

My conclusion is that the servlet mapping/url pattern handling for Glassfish V3.0.1 has some issues, the precise nature of which is not clear. My solution is to use “.xhtml” for the actual filetypes and for the default suffix, and extension mapping using “*.jsf” for the url pattern – this combination works fine with no issues.

No Comments »

June 11th, 2010
12:44 pm
Further notes on EJB Lookups

Posted under Glassfish
Tags , ,

Much of this has already been covered here, but I am posting these somewhat raw notes from an earlier investigative email as they include one or two links and points not covered elsewhere. I don’t have the time or inclination at present to rework everything into an existing post :-

 

1/ For local beans, you can just use defaults in @Stateless (in the bean) and in @EJB (in the referring code)
Note that when you do not use all the defaults, you must declare both the beaninterface and the name attributes

@EJB(name=”ejb/JPAGlassFishIce/SimpleBean”, beanInterface=SimpleBeanLocal.class)
private SimpleBean simpleBean;
2/ For remote beans, you can use e.g.

@Stateless(mappedName=”ejb/JPAGlassFishIceEJB/SimpleBean”)

Then

@EJB(beanInterface=SimpleBeanRemote.class, mappedName=”ejb/JPAGlassFishIceEJB/SimpleBean”)
private SimpleBean simpleBean;

Note – you must pass the class of the remote interface as above or it will not work, and you just get name not found exception.

3/ The above methods work for both access from one bean to another, and from a JSF managed bean to a remote (or local) bean
It also works from any POJO called from e.g. a JSF manged bean.
Note that this ability is container specific – Glassfish does it, other containers may vary in what/if/how they support.

4/ If doing JNDI lookups yourself to a local bean (via context.lookup), you need to add <ejb-local-ref> to web.xml as follows :-

 <ejb-local-ref>
    <ejb-ref-name>ejb/JPAGlassFishIce/SimpleBean</ejb-ref-name>
    <ejb-ref-type>Session</ejb-ref-type>
    <local-home></local-home>
    <local>uk.co.salientsoft.jpaglassfishice.domain.SimpleBeanLocal</local>
</ejb-local-ref>

This would be used if using e.g. Spring or a custom EL resolver  to inject references into JSF managed beans (via JSF DI)

Note that the JNDI name for the above local reference would be
“java:comp/env/ejb/JPAGlassFishIce/SimpleBean”
i.e. this is picking up from the <ejb-ref-name> above, and is prefixed java:comp/env
java:comp/env is a reference to the JNDI “Environment” service provider for Java EE
you can also use this  to look up environment variables etc.
see here http://java.sun.com/developer/technicalArticles/xml/WebAppDev4/

The <ejb-local-ref> stuff is done for you automatically if you use @EJB

5/ Note that JNDI names are container specific at present (fixed in java ee6)
See here for a good SUN post on all the EJB reference stuff :-
https://glassfish.dev.java.net/javaee5/ejb/EJB_FAQ.html

No Comments »

December 1st, 2009
11:38 am
EJB referencing/JNDI mapping examples in JSF/Glassfish

Posted under Glassfish
Tags , , ,

Update

I have posted some further notes on this here. The notes are in raw form from an earlier investigative email – much of it is covered here, but some points and links are not, and I do not have the time or inclination at present to rework everything into a single post!

The following examples show typical scenarios which have been tested as working :-

1/ Local EJB Interface injected into JSF managed bean via @EJB

Note that when implementing a dual interface as here, you can extend a single underlying interface. In this case, SimpleBeanLocal and SimpleBeanRemote both extend SimpleBean. However, when you do this, the implementation code must explicitly implemement both SimpleBeanLocal and SimpleBeanRemote as in this example. Implementing the superinterface SimpleBean on its own will not work. This is also explained in this post.

JSF managed bean code

@EJB()
private SimpleBean simpleBean;

 

EJB Implementation Code

@Stateless()
public class SimpleBeanImpl implements SimpleBeanLocal, SimpleBeanRemote {

...class code here...

}

 

 

2/ Local EJB Interface looked up in JSF managed bean directly via JNDI 

JSF managed bean code

try {
  InitialContext ctx = new InitialContext();

  /* Note that the JNDI name consists of the Java EE Environment Naming Context (ENC) -
    "java:comp/env", followed by "/", followed by the <ejb-ref-name> used in web.xml.
    The extra /Local is just to make the name different to the remote example.
    Any name can be used providing web.xml matches, and multiple slashes can be present.
  */

  simpleBean = (SimpleBean) ctx.lookup("java:comp/env/ejb/JPAGlassFishIce/Local/SimpleBean");     
  userList = simpleBean.fetchUsers();
} catch (NamingException e1) {
  e1.printStackTrace();
}

 

web.xml

<!-- We define a reference for the bean here.
     If we were using @EJB this would do it for us,
     but in this case we are using an explicit JNDI lookup.
-->
<ejb-local-ref>
    <ejb-ref-name>ejb/JPAGlassFishIce/Local/SimpleBean</ejb-ref-name>
    <ejb-ref-type>Session</ejb-ref-type>
    <local-home></local-home>
    <local>uk.co.salientsoft.jpaglassfishice.domain.SimpleBeanLocal</local>
</ejb-local-ref>

 

EJB Implementation Code

@Stateless()
public class SimpleBeanImpl implements SimpleBeanLocal, SimpleBeanRemote {

...class code here...

}

 

 

3/ Remote EJB Interface injected into JSF managed bean via @EJB

JSF managed bean code

@EJB(name="ejb/JPAGlassFishIce/SimpleBean", beanInterface=SimpleBeanRemote.class)
private SimpleBean simpleBean;

 

EJB Implementation Code

@Stateless(mappedName="ejb/JPAGlassFishIceEJB/SimpleBean")
public class SimpleBeanImpl implements SimpleBeanLocal, SimpleBeanRemote {

...class code here...

}

 

 

4/ Remote EJB Interface looked up in JSF managed bean directly via JNDI 

JSF managed bean code

try {
  InitialContext ctx = new InitialContext();

  /* Note that the JNDI name here matches the mappedName given in the
     @Stateless annotation in the EJB implementation code.
     mappedName is only relevant for remote interfaces.
     It is not used for a local interface.
  */

  simpleBean = (SimpleBean) ctx.lookup=("ejb/JPAGlassFishIceEJB/SimpleBean");     
  userList = simpleBean.fetchUsers();
} catch (NamingException e1) {
  e1.printStackTrace();
}

 

EJB Implementation Code

@Stateless(mappedName="ejb/JPAGlassFishIceEJB/SimpleBean")
public class SimpleBeanImpl implements SimpleBeanLocal, SimpleBeanRemote {

...class code here...

}

No Comments »

November 30th, 2009
5:28 pm
Accessing Local and Remote EJBs in Glassfish

Posted under Glassfish
Tags , , ,

This Glassfish article  is a must read reference on the naming and JNDI minefield when looking up local and remote EJBs.
There is also a very  informative Refcardz card on this topic. Refcardz can be downloaded as PDFs if  you register.
In my experience, there is a lot of misinformation around the internet on this which can be time consuming to weed out.

I’ve posted some examples of local and remote EJB access via both injection and JNDI here.

Here are some key points I worked through and learned :-

  1. Despite a number of blog posts to the contrary, EJBs can be injected via @EJB into JSF managed beans, POJOs called from managed beans, and servlets provided the JSF/servlets are running in the EJB container, e.g. if Glassfish is used both as servlet and EJB container.
  2. When injecting local EJBs, using the defaults on @EJB and matching defaults e.g. on @Stateless will work and the bean will inject.
  3. When injecting remote EJBs via @EJB, use the mappedName argument to specify the JNDI name of the remote bean. It is also essential to specify the class of the remote EJB interface in the beanInterface argument to @EJB. Failure to do this will result in NamingExceptions, which can give the misleading impression that it is the JNDI name that is wrong.
  4. If @EJB is not used, then <ejb-local-ref> may be used in web.xml to define a reference to the bean. If @EJB is used then this is handled automatically. The above Glassfish article details how the various fields in @EJB and <ejb-local-ref> are related.
  5. In addition to @EJB and direct JNDI lookups, EJBs can be injected via JSF using a custom EL resolver which performs the JNDI lookups and injections performed in faces-config.xml.  An interesting example of a custom EL resolver to do this is here. However, for injecting EJBs,  @EJB requires no extra code. It is also possible to inject EJBs via Spring, into beans managed by a Spring container. However these have not been pursued as @EJB is the easiest way. It would be overkill to use a Spring container purely for EJB injection/service location.

No Comments »