Bug 1013888 - Load application configuration from a configuration file
Summary: Load application configuration from a configuration file
Keywords:
Status: CLOSED CURRENTRELEASE
Alias: None
Product: PressGang CCMS
Classification: Community
Component: CCMS-Core
Version: 1.1
Hardware: Unspecified
OS: Unspecified
unspecified
unspecified
Target Milestone: ---
: 1.3
Assignee: Lee Newson
QA Contact:
URL:
Whiteboard:
Depends On:
Blocks: 1032348
TreeView+ depends on / blocked
 
Reported: 2013-10-01 02:05 UTC by Lee Newson
Modified: 2013-12-03 22:16 UTC (History)
1 user (show)

Fixed In Version:
Doc Type: Bug Fix
Doc Text:
Clone Of:
Environment:
Last Closed: 2013-12-03 22:16:16 UTC
Embargoed:


Attachments (Terms of Use)

Description Lee Newson 2013-10-01 02:05:40 UTC
Currently a lot of PressGang's application and entity constants are hard coded and as such are a pain to try and use outside of Red Hat. We should update this to load the details from configuration files (or a database table) so that they can be changed on a per instance basis. The REST API should then be extended to allow reading/writing to those values so they can be updated at runtime (where possible)

Comment 1 Lee Newson 2013-11-19 02:09:03 UTC
This is now currently working on the server and the csprocessor.

There are two configuration files that need to be configured now: application.properties and entities.properties. The location of these files is determined by the "pressgang.config.dir" system property. If that property isn't specified then it will attempt to use the ${jboss.server.config.dir}/pressgang/ directory and if the ${jboss.server.config.dir} property doesn't exist it will use the current directory.

The entities configuration file will be validated to ensure that all the required database entities have been configured. If a value has been left blank or is missing completely then an error will be logged and the application will fail to start.

For example configuration files see https://github.com/pressgang-ccms/PressGangCCMSREST/tree/devel

As for configuring the values during runtime, I've added two new endpoints:

GET  http://<HOST:PORT>/pressgang-ccms/rest/1/settings/get/json
POST http://<HOST:PORT>/pressgang-ccms/rest/1/settings/update/json

Note however that entity values can't be changed at runtime because the entity ids should not be changed once they are created, so only the application settings can be changed.

As for adding new values during runtime there are two collections "undefinedSettings" and "undefinedEntities" in the response. Each collection contains a list of key value pairs which can be used to add additional settings/entities without having to recompile the application.

Comment 2 Lee Newson 2013-11-20 02:47:12 UTC
The UI has now been updated to load the server settings/entity ids instead of using hard coded values.

One thing to note that hasn't been migrated at this stage is the Help Topic IDs (since that is UI specific), as such BZ#1032352 has been opened to address that.

Note: This is now live on the development/test server.

Comment 4 Matthew Casperson 2013-11-26 05:42:40 UTC
The dev server noew has the option to select the local host. If you select it without actually having a server at localhost the call to http://localhost:8080/pressgang-ccms/rest/1/settings/get/json fails and the UI won't load. I'm trying to track down the cause of this, but I'll note it here in case it is relevant.

Comment 5 Matthew Casperson 2013-11-26 05:56:26 UTC
In the case where the server can not be contacted, the ServerSettingsReceived event is never tiggered, and the UI is not displayed at all. This prevents anyone from selecting a new server.

I have changed the code to the following:

            failOverRESTCall.performRESTCall(
                    FailOverRESTCallDatabase.getServerSettings(),
                    new RESTCallBack<RESTServerSettingsV1>() {
                        public void success(@NotNull final RESTServerSettingsV1 value) {
                            serverSettings = value;
                            initialised = true;

                            eventBus.fireEvent(new ServerSettingsReceived(value));
                        }

                        public void failed() {
                            eventBus.fireEvent(new ServerSettingsReceived(null));
                        }
                    },
                    null,
                    true
            );

The addition of the failed method is only a hack though, as when the UI is constructed it will attempt to load null variables.

This also does not address the issue of reloading the config when a new server is selected. serverSettings.get().loadSettings() is only called once in AppController.go(). It should be called whenever a server from a new server group is selected.

Comment 6 Matthew Casperson 2013-11-26 05:57:33 UTC
Actually, ignore that last comment, because the page is reloaded when a new server group is selected.

Comment 7 Lee Newson 2013-11-26 22:40:41 UTC
I've reworked how the server settings are loaded in the UI and they are now loaded on a per page basis. This will remove the problem above as it'll only be loaded as its needed and also I've enable the default error handler so it'll act the same way as it used to if the server couldn't be contacted.

This version is currently live on the development/test server.

Additional Note:
I've implemented this in a similar way to getting ServerDetails, so that all calls look like an asynchronous call, however only the first will be and then any following calls will actually be synchronous.

Comment 8 Lee Newson 2013-11-26 22:43:22 UTC
The reason for reworking the UI to load the settings per view is so that any changes to the config will be picked up without having all users reload there page.

Comment 9 Matthew Casperson 2013-11-28 04:41:51 UTC
Confirmed that I could get the server settings with the GET request.

Confirmed that I could add a undefinedSetting with the following post:

{
"configuredParameters":["undefinedSettings"],
"undefinedSettings":{"items":[{"state":1, "item":{"configuredParameters":["key","value"],"key":"test","value":"testvalue"}}]}
}

Comment 10 Matthew Casperson 2013-11-28 04:42:53 UTC
Confirmed that I could add an undefined entity with the post:

{
"configuredParameters":["entities"],
"entities":{"configuredParameters":["undefinedEntities"], "undefinedEntities": {"items":[{"state":1, "item":{"configuredParameters":["key","value"],"key":"testentity","value":1}}]}}
}

Comment 11 Matthew Casperson 2013-11-28 04:43:44 UTC
Confirmed that both HTTP POST updates also updates the properties files.

Comment 12 Matthew Casperson 2013-11-28 05:02:13 UTC
Posting

{"configuredParameters":["docBookElements"], "docBookTemplateIds":[1]}

results in 

org.jboss.resteasy.spi.UnhandledException: java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
	org.jboss.resteasy.core.SynchronousDispatcher.handleApplicationException(SynchronousDispatcher.java:365)
	org.jboss.resteasy.core.SynchronousDispatcher.handleException(SynchronousDispatcher.java:233)
	org.jboss.resteasy.core.SynchronousDispatcher.handleInvokerException(SynchronousDispatcher.java:209)
	org.jboss.resteasy.core.SynchronousDispatcher.getResponse(SynchronousDispatcher.java:557)
	org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:524)
	org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:126)
	org.jboss.resteasy.plugins.server.servlet.ServletContainerDispatcher.service(ServletContainerDispatcher.java:208)
	org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher.service(HttpServletDispatcher.java:55)
	org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher.service(HttpServletDispatcher.java:50)
	javax.servlet.http.HttpServlet.service(HttpServlet.java:847)
	net.bull.javamelody.MonitoringFilter.doFilter(MonitoringFilter.java:163)
	org.jboss.pressgang.ccms.server.servlet.filter.GZIPCompressionFilter.doFilter(GZIPCompressionFilter.java:85)
	com.thetransactioncompany.cors.CORSFilter.doFilter(CORSFilter.java:156)
	com.thetransactioncompany.cors.CORSFilter.doFilter(CORSFilter.java:233)
JBWEB000071: root cause

java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
	org.jboss.pressgang.ccms.model.config.ApplicationConfig.getDocBookTemplateStringConstantIds(ApplicationConfig.java:80)
	org.jboss.pressgang.ccms.server.rest.v1.ServerSettingsV1Factory.createRESTEntity(ServerSettingsV1Factory.java:35)
	org.jboss.pressgang.ccms.server.rest.v1.ServerSettingsV1Factory$Proxy$_$$_WeldClientProxy.createRESTEntity(ServerSettingsV1Factory$Proxy$_$$_WeldClientProxy.java)
	org.jboss.pressgang.ccms.server.rest.v1.RESTv1.updateJSONServerSettings(RESTv1.java:456)
	org.jboss.pressgang.ccms.server.rest.v1.RESTv1$Proxy$_$$_WeldClientProxy.updateJSONServerSettings(RESTv1$Proxy$_$$_WeldClientProxy.java)
	sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
	sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	java.lang.reflect.Method.invoke(Method.java:606)
	org.jboss.resteasy.core.MethodInjectorImpl.invoke(MethodInjectorImpl.java:167)
	org.jboss.resteasy.core.ResourceMethod.invokeOnTarget(ResourceMethod.java:269)
	org.jboss.resteasy.core.ResourceMethod.invoke(ResourceMethod.java:227)
	org.jboss.resteasy.core.ResourceMethod.invoke(ResourceMethod.java:216)
	org.jboss.resteasy.core.SynchronousDispatcher.getResponse(SynchronousDispatcher.java:542)
	org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:524)
	org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:126)
	org.jboss.resteasy.plugins.server.servlet.ServletContainerDispatcher.service(ServletContainerDispatcher.java:208)
	org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher.service(HttpServletDispatcher.java:55)
	org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher.service(HttpServletDispatcher.java:50)
	javax.servlet.http.HttpServlet.service(HttpServlet.java:847)
	net.bull.javamelody.MonitoringFilter.doFilter(MonitoringFilter.java:163)
	org.jboss.pressgang.ccms.server.servlet.filter.GZIPCompressionFilter.doFilter(GZIPCompressionFilter.java:85)
	com.thetransactioncompany.cors.CORSFilter.doFilter(CORSFilter.java:156)
	com.thetransactioncompany.cors.CORSFilter.doFilter(CORSFilter.java:233)

Comment 13 Lee Newson 2013-11-28 05:21:35 UTC
Fixed in 1.3-SNAPSHOT build 201311281517

The problem was that the getter for the list was assuming that the stored value was a list of Strings which is the case when it's loaded, however after updating the value it is a list of Integers.

Note: This version is now live on the development/test server.

Comment 14 Matthew Casperson 2013-11-28 23:11:47 UTC
Confirmed that posting arrays of intergers works, and that the configuredParameters names match the property names.


Note You need to log in before you can comment on or make changes to this bug.