[GLASSFISH-20789] Failed to create cluster with jms option Created: 02/Sep/13  Updated: 19/Sep/14  Resolved: 09/Sep/13

Status: Resolved
Project: glassfish
Component/s: admin_gui
Affects Version/s: 4.1
Fix Version/s: 4.1

Type: Bug Priority: Major
Reporter: Jeremy_Lv Assignee: Anissa Lam
Resolution: Fixed Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified
Environment:

All


Attachments: PNG File error.png     Text File revision.patch    
Tags: 40-regression, admin-gui, jersey

 Description   

When I tried to create a cluster as the picture I have attached shows, It is failed because of the "java.lang.ClassCastException:".

Here's some of the failure exception in the server.log:
[2013-08-30T17:37:28.473+0800] [glassfish 4.0] [SEVERE] [] [org.glassfish.admingui] [tid: _ThreadID=47 _ThreadName=admin-listener(4)] [timeMillis: 1377855448473] [levelValue: 1000] [[
java.lang.Boolean cannot be cast to java.lang.String;
java.lang.ClassCastException: java.lang.Boolean cannot be cast to java.lang.String;
restRequest: endpoint=http://localhost:4848/management/domain/clusters/cluster/cluster1/configure-jms-cluster
attrs=

{availabilityEnabled=false, clustertype=conventional, messageStoreType=file, configStoreType=masterbroker, property=prop1=value1:prop2=value2\:with\:colons:prop3=value3}

method=post]]

BTW: I have also confirmed that the cluster with jms option can be created in the glassfish v3.1.2, but it is failed in the glassfish v4. So I regarded it as a rollback issue in the glassfish v4.



 Comments   
Comment by Jeremy_Lv [ 02/Sep/13 ]

Hi, Anissa:
After a few investigation about the glassfish, I found it is cause by the following code:

AbstractFormProvider.java
    public <M extends MultivaluedMap<String, String>> void writeTo(
            M t,
            MediaType mediaType,
            OutputStream entityStream) throws IOException {
        final String charsetName = ReaderWriter.getCharset(mediaType).name();

        final StringBuilder sb = new StringBuilder();
        for (Map.Entry<String, List<String>> e : t.entrySet()) {    
         ★  for (String value : e.getValue()) {  ★
                if (sb.length() > 0) {
                    sb.append('&');
                }
                sb.append(URLEncoder.encode(e.getKey(), charsetName));
                if (value != null) {
                    sb.append('=');
                    sb.append(URLEncoder.encode(value, charsetName));
                }
            }
        }

It is because some of the value's type in the Map.Entry is boolean, however, it is because the boolean can't be cast to the String here so that it is failed to create the cluster with jms options.

Thanks
Jeremy Lv

Comment by Jeremy_Lv [ 02/Sep/13 ]

I also confirmed the early version of jersey does't have the AbstractFormProvider.java, it seems the AbstractFormProvider.java has imported when it comes to the glassfish v4

Comment by Jeremy_Lv [ 03/Sep/13 ]

Hi, Anissa:

I have confirmed this issue is caused by the upgrade of the jersey. After I have ignore the value of availabilityEnabled the cluster with jms options can be created successfully.

I have also confirmed the value of availabilityEnabled can't be added to the formData when create cluster with jms options in glassfish v3. So IMHO, I have revised the source as follows:

RestUtil.java
Index: src/main/java/org/glassfish/admingui/common/util/RestUtil.java
===================================================================
--- src/main/java/org/glassfish/admingui/common/util/RestUtil.java	(revision 62446)
+++ src/main/java/org/glassfish/admingui/common/util/RestUtil.java	(working copy)
@@ -554,6 +554,9 @@
             } else {
                 //formData.putSingle(key, (value != null) ? value.toString() : value);
                 try {
+                    //ignore the value of availabilityEnabled as it is useless
+                    if (key.equals("availabilityEnabled"))
+                        continue;
                     formData.putSingle(key, value);
                 } catch (ClassCastException ex) {
                     Logger logger = GuiUtil.getLogger();

In the glassfish v3, the sentence of formData.putSingle(key, value); will only storage the value which type is String, So it will regardless the value of availabilityEnabled as the type is boolean. However, when it comes to the glassfish v4, as the jersey side code upgrade, the sentence of formData.putSingle(key, value); will storage the every type of value including the boolean type, but the element of availabilityEnabled is useless when it comes to create the cluster with jms options. After all, I just do some changes to exclude the element of availabilityEnabled and the cluster with jms options can be created successfully.

Could you help me to confirm about my changes? I have also attached my patch in the JIRA.

Thanks
Jeremy Lv

Comment by Jeremy_Lv [ 03/Sep/13 ]

I have also ran the QL tests after I have applied the changes and all of the tests have passed, please review my changes whether it is fine for me to check in?

Thanks a lot!

Comment by Anissa Lam [ 04/Sep/13 ]

Thanks for suggesting the fix.
I need to take a closer look about this availabilityEnabled option in creating the cluster.
Will get back to you in a day or 2.

Comment by Anissa Lam [ 05/Sep/13 ]

I have looked at the patch. This issue need to be solved in another way.
buildMultivalueMap() is called everytime before doing a POST. Making changes in this has to be very careful as it may affect other commands, it is a very high risk change.
In fact, deploying an application will also go through this method. Thus if the availabilityEnabled option is selected when deploying the application to a cluster or other standalone instance, this option will be 'removed' by the new change, and thus the application will NOT be deployed correctly as the user request.
Need to figure out another more localized changes to fix this issue.

thanks for the suggestion though.

Comment by Jeremy_Lv [ 06/Sep/13 ]

Hi, Anissa:

Thanks for confirmation, I have a question about this issue:
1). what the option of availabilityEnabled used for when create the cluster with jms options, if the option is useless(As I can't find out anywhere to use this options here), how about delete availabilityEnabled related setting in the jmsHandlers.inc like this:

jmsHandlers.inc
Index: jmsHandlers.inc
===================================================================
--- jmsHandlers.inc	(revision 61862)
+++ jmsHandlers.inc	(working copy)
@@ -45,11 +45,9 @@
     //println("***** #{pageSession}\n\n\n\n\n\n");
     mapPut(map="#{requestScope.jmsAttrs}" key="clustertype" value="$pageSession{clusterType}");
     mapPut(map="#{requestScope.jmsAttrs}" key="property" value="$pageSession{properties}");
-    mapPut(map="#{requestScope.jmsAttrs}" key="availabilityEnabled" value="#{true}");
     if ('$pageSession{clusterType}=conventional') {
         mapPut(map="#{requestScope.jmsAttrs}" key="configStoreType" value="$pageSession{configStoreType}");
         mapPut(map="#{requestScope.jmsAttrs}" key="messageStoreType" value="$pageSession{messageStoreType}");
-        mapPut(map="#{requestScope.jmsAttrs}" key="availabilityEnabled" value="#{false}");
     }
 
     // Save JMS integration type

However, I have also tried to convert the availabilityEnabled's value from boolean to String, However, it will throw out the exception that the availabilityEnabled is an invalid option:

2013-09-06T10:14:50.640+0800] [glassfish 4.0] [SEVERE] [NCLS-CORE-00003] [javax.enterprise.system.core] [tid: _ThreadID=45 _ThreadName=admin-listener(3)] [timeMillis: 1378433690640] [levelValue: 1000] [[
  Exception while running a command
MultiException stack 1 of 1
java.lang.IllegalArgumentException:  Invalid option: availabilityEnabled
	at com.sun.enterprise.v3.admin.CommandRunnerImpl.validateParameters(CommandRunnerImpl.java:1026)
	at com.sun.enterprise.v3.admin.CommandRunnerImpl.doCommand(CommandRunnerImpl.java:1192)
	at com.sun.enterprise.v3.admin.CommandRunnerImpl.access$1300(CommandRunnerImpl.java:109)
	at com.sun.enterprise.v3.admin.CommandRunnerImpl$ExecutionContext.execute(CommandRunnerImpl.java:1846)
	at com.sun.enterprise.v3.admin.CommandRunnerImpl$ExecutionContext.execute(CommandRunnerImpl.java:1722)
	at org.glassfish.admin.rest.utils.ResourceUtil.runCommand(ResourceUtil.java:253)
	at org.glassfish.admin.rest.utils.ResourceUtil.runCommand(ResourceUtil.java:231)
	at org.glassfish.admin.rest.resources.TemplateExecCommand.executeCommandLegacyFormat(TemplateExecCommand.java:157)
	at org.glassfish.admin.rest.resources.TemplateCommandPostResource.processPostLegacyFormat(TemplateCommandPostResource.java:97)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:601)
	at org.glassfish.jersey.server.model.internal.ResourceMethodInvocationHandlerFactory$1.invoke(ResourceMethodInvocationHandlerFactory.java:81)
	at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher$1.run(AbstractJavaResourceMethodDispatcher.java:140)
	at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.invoke(AbstractJavaResourceMethodDispatcher.java:158)
	at org.glassfish.jersey.server.model.internal.JavaResourceMethodDispatcherProvider$ResponseOutInvoker.doDispatch(JavaResourceMethodDispatcherProvider.java:152)
	at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.dispatch(AbstractJavaResourceMethodDispatcher.java:101)
	at org.glassfish.jersey.server.model.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:353)
	at org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:343)
	at org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:102)
	at org.glassfish.jersey.server.ServerRuntime$1.run(ServerRuntime.java:237)
	at org.glassfish.jersey.internal.Errors$1.call(Errors.java:271)
	at org.glassfish.jersey.internal.Errors$1.call(Errors.java:267)
	at org.glassfish.jersey.internal.Errors.process(Errors.java:315)
	at org.glassfish.jersey.internal.Errors.process(Errors.java:297)
	at org.glassfish.jersey.internal.Errors.process(Errors.java:267)
	at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:318)
	at org.glassfish.jersey.server.ServerRuntime.process(ServerRuntime.java:211)
	at org.glassfish.jersey.server.ApplicationHandler.handle(ApplicationHandler.java:982)
	at org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpContainer.service(GrizzlyHttpContainer.java:330)
	at org.glassfish.admin.rest.adapter.RestAdapter$2.service(RestAdapter.java:316)
	at org.glassfish.admin.rest.adapter.RestAdapter.service(RestAdapter.java:179)
	at com.sun.enterprise.v3.services.impl.ContainerMapper$HttpHandlerCallable.call(ContainerMapper.java:496)
	at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:175)
	at org.glassfish.grizzly.http.server.HttpHandler.runService(HttpHandler.java:191)
	at org.glassfish.grizzly.http.server.HttpHandler.doHandle(HttpHandler.java:168)
	at org.glassfish.grizzly.http.server.HttpServerFilter.handleRead(HttpServerFilter.java:187)
	at org.glassfish.grizzly.filterchain.ExecutorResolver$9.execute(ExecutorResolver.java:119)
	at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeFilter(DefaultFilterChain.java:288)
	at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeChainPart(DefaultFilterChain.java:206)
	at org.glassfish.grizzly.filterchain.DefaultFilterChain.execute(DefaultFilterChain.java:136)
	at org.glassfish.grizzly.filterchain.DefaultFilterChain.process(DefaultFilterChain.java:114)
	at org.glassfish.grizzly.ProcessorExecutor.execute(ProcessorExecutor.java:77)
	at org.glassfish.grizzly.nio.transport.TCPNIOTransport.fireIOEvent(TCPNIOTransport.java:837)
	at org.glassfish.grizzly.strategies.AbstractIOStrategy.fireIOEvent(AbstractIOStrategy.java:113)
	at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.run0(WorkerThreadIOStrategy.java:115)
	at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.access$100(WorkerThreadIOStrategy.java:55)
	at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy$WorkerThreadRunnable.run(WorkerThreadIOStrategy.java:135)
	at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:565)
	at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.run(AbstractThreadPool.java:545)
	at java.lang.Thread.run(Thread.java:722)
]]

[2013-09-06T10:14:50.666+0800] [glassfish 4.0] [SEVERE] [] [org.glassfish.admingui] [tid: _ThreadID=124 _ThreadName=admin-listener(6)] [timeMillis: 1378433690666] [levelValue: 1000] [[
  RestResponse.getResponse() gives FAILURE.  endpoint = 'http://localhost:4848/management/domain/clusters/cluster/c1/configure-jms-cluster'; attrs = '{availabilityEnabled=false, clustertype=conventional, messageStoreType=file, configStoreType=masterbroker, property=null}']]
Comment by Jeremy_Lv [ 06/Sep/13 ]

After checking about the jms side code, I have found the jms command doesn't support the option of availabilityEnabled, You can check about the ConfigureJMSCluster.java and you will found there's no defination about the option of availabilityEnabled.

Comment by Jeremy_Lv [ 06/Sep/13 ]

If we want the command support the option of availabilityEnabled, I think the changes would be like follows:

Index: admingui/common/src/main/java/org/glassfish/admingui/common/handlers/RestApiHandlers.java
===================================================================
--- admingui/common/src/main/java/org/glassfish/admingui/common/handlers/RestApiHandlers.java	(revision 62681)
+++ admingui/common/src/main/java/org/glassfish/admingui/common/handlers/RestApiHandlers.java	(working copy)
@@ -212,6 +212,10 @@
                     @HandlerOutput(name="result", type=Map.class)})
     public static void restRequest(HandlerContext handlerCtx) {
         Map<String, Object> attrs = (Map<String, Object>) handlerCtx.getInputValue("attrs");
+        if (attrs != null && attrs.containsKey(("availabilityEnabled"))){
+            String value = String.valueOf(attrs.get("availabilityEnabled"));
+            attrs.put("availabilityEnabled", value);
+        }
         String endpoint = (String) handlerCtx.getInputValue("endpoint");
         String method = (String) handlerCtx.getInputValue("method");
         boolean quiet = (Boolean) handlerCtx.getInputValue("quiet");
Index: jms/admin/src/main/java/org/glassfish/jms/admin/cli/ConfigureJMSCluster.java
===================================================================
--- jms/admin/src/main/java/org/glassfish/jms/admin/cli/ConfigureJMSCluster.java	(revision 62681)
+++ jms/admin/src/main/java/org/glassfish/jms/admin/cli/ConfigureJMSCluster.java	(working copy)
@@ -116,6 +116,9 @@
     @Param(name="configstoretype", optional=true, alias="cs")
     String configStoreType;
 
+    @Param(name="availabilityEnabled", optional=true, alias="ae")
+    String availabilityEnabled;
+
     @Param(name="messagestoretype", optional=true, alias="ms")
     String messageStoreType;

However, if we change like this, the option of availabilityEnabled will be avaiable when type as "configure-jms-cluster", As I can't find out any use of the availabilityEnabled option, I suggest to delete availabilityEnabled related setting in the jmsHandlers.inc.

Thanks
Jeremy Lv

Comment by Anissa Lam [ 06/Sep/13 ]

Let me check with the jms team about this availabilityEnabled option and get back to you.

Comment by Ed Bratt [ 06/Sep/13 ]

Clusters aren't fully tested in this GlassFish release as our focus was to deliver the content necessary for the Java EE RI. No doubt there will be issues (this appears to be one).
You may already know this, but you can manually configure a JMS cluster with ASAdmin commands. Here is an outline of the steps:
1. asadmin start-domain
2. asadmin create-cluster <cluster-name>
3. set jms-service type if necessary, e.g.
asadmin set <cluster-name>.jms-service.type=LOCAL
4. run configure-jms-cluster, e.g setup for enhanced cluster (where <gf-passfile> contains db password setting AS_ADMIN_JMSDBPASSWORD=<db-password>)
asadmin --passwordfile <gf-passfile> configure-jms-cluster --clustertype=enhanced --dbvendor=<vendor> --dbuser=<db-user-name> --dburl=<db-url> <cluster-name>
5. create instances, e.g. to creat a local instance
asadmin create-local-instance --cluster <cluster-name> <instance-name>
6. create any JMS resources
7. asadmin start-cluster

If you want to use high-availability DB for GlassFish MQ, e.g. --clustertype=enhanced copy the JDBC driver to
<glassfish-install-root>/glassfish4/mq/lib/ext/ before step 1 above.
(We tried this and it appears to work.)

Comment by Jeremy_Lv [ 07/Sep/13 ]

Hi, Ed Bratt:

I have tried about this too and it seems to work without availabilityEnabled options in the admin command. So is it no need to add the availabilityEnabled options in the command side?

Comment by Jeremy_Lv [ 09/Sep/13 ]

I have checked in the changes as the version 62705 to delete the availabilityEnabled options in the admin console.

Comment by amyk [ 09/Sep/13 ]

To clarify, 'availabilityEnabled' is not an option for 'asadmin configure-jms-cluster'

GlassFish 3.1.2

asadmin configure-jms-cluster --help
SYNOPSIS
configure-jms-cluster [--help]
[--clustertype=

{conventional|enhanced}]
[--configstoretype={masterbroker|shareddb}]
[--messagestoretype={file|jdbc}]
[--dbvendor database-vendor]
[--dbuser database-user]
[--dburl database-url]
[--property property-list]
cluster-name

GlassFish 4.0

asadmin configure-jms-cluster --help
SYNOPSIS
configure-jms-cluster [--help]
[--clustertype={conventional|enhanced}

]
[--configstoretype=

{masterbroker|shareddb}

]
[--messagestoretype=

{file|jdbc}

]
[--dbvendor database-vendor]
[--dbuser database-user]
[--dburl database-url]
[--property (name=value)[:name=value]*]
cluster-name

Comment by Jeremy_Lv [ 09/Sep/13 ]

Hi, Amyk:

Thanks for your clarification!

Comment by amyk [ 10/Sep/13 ]

From David Zhao:

The 'availabilityEnabled' was removed (no longer needed) for configuring JMS cluster, by the following revision for a long time:

Revision: 42142
Time: 10/26/2010 02:46 PM
Author: sats
Path: v3/jms/admin/src/main/java/org/glassfish/jms/admin/cli/ConfigureJMSCluster.java (trunk)
Message: changes to the configure-jms-cluster command as per ASARCH and MQ team suggestions

Comment by Jeremy_Lv [ 10/Sep/13 ]

amyk:

Your comments added here help me a lot! Thanks again!

Generated at Wed May 06 21:09:01 UTC 2015 using JIRA 6.2.3#6260-sha1:63ef1d6dac3f4f4d7db4c1effd405ba38ccdc558.