# Adding Settings

**URL:** <https://forum.inductiveautomation.com/t/adding-settings/30059>\
**Category:** Module Development\
**Created:** [November 18, 2019, 7:04pm UTC](https://forum.inductiveautomation.com/t/adding-settings/30059 "2019-11-18T19:04:12Z")\
**Posts on this page:** 18\
**Page:** 1

<div class="post-metadata">

**Author:** ![jose](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/jose/32/11908_2.png) [@jose](https://forum.inductiveautomation.com/u/jose)\
**Post date:** [November 18, 2019, 7:04pm UTC](https://forum.inductiveautomation.com/t/adding-settings/30059/1 "2019-11-18T19:04:12Z")

</div>

Pretty new to Ignition Development  
I want to add a settings page to my module, I have created an registered a PersistentRecord but it doesn’t show up anywhere in the settings page.  
What am I missing?  
Here’s my current PersistentClass

```auto
package com.jnjdodev.ignition.modules.websocket;

import com.inductiveautomation.ignition.gateway.localdb.persistence.Category;
import com.inductiveautomation.ignition.gateway.localdb.persistence.IdentityField;
import com.inductiveautomation.ignition.gateway.localdb.persistence.IntField;
import com.inductiveautomation.ignition.gateway.localdb.persistence.PersistentRecord;
import com.inductiveautomation.ignition.gateway.localdb.persistence.RecordMeta;

import simpleorm.dataset.SFieldFlags;

public class WebSocketsRecord extends PersistentRecord {

	
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	public static final RecordMeta<WebSocketsRecord> META = new RecordMeta<>(
			WebSocketsRecord.class, "WebSocketsRecord").setNounKey("WebSocketsRecord.Noun")
            .setNounPluralKey("WebSocketsRecord.Noun.Plural");

	public static final IdentityField Id = new IdentityField(META);
	
	
	 public static final IntField WebSocketPort = new IntField(META, "WebSocketPort",
	            SFieldFlags.SMANDATORY).setDefault(23333);
	@Override
	public RecordMeta<?> getMeta() {
		// TODO Auto-generated method stub
		return META;

	}
	

	public void setPort(int port)
	{
		this.setInt(WebSocketPort, port);
	}
	
	public int getPort()
	{
		return this.getInt(WebSocketPort);
	}

	static final Category SeeqServerConfiguration =
            new Category("WebSocketsRecord.Category.Configuration", 1000)
                    .include(WebSocketPort);
}

```

and my GatewayHook Setup

```auto
public void setup(GatewayContext context) {
		// TODO Auto-generated method stub
		this.context = context; 
		try {
			this.context.getSchemaUpdater().updatePersistentRecords(WebSocketsRecord.META);
			
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

```

---

<div class="post-metadata">

**Author:** ![pturmel](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pturmel/32/3295_2.png) [@pturmel](https://forum.inductiveautomation.com/u/pturmel)\
**Post date:** [November 18, 2019, 7:44pm UTC](https://forum.inductiveautomation.com/t/adding-settings/30059/2 "2019-11-18T19:44:52Z")

</div>

You have to construct one or more configuration pages to be shown, and override the gateway hook’s getConfigPages() method. Welcome to Wicket!

---

<div class="post-metadata">

**Author:** ![Kevin.Herron](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/kevin.herron/32/7259_2.png) [@Kevin.Herron](https://forum.inductiveautomation.com/u/Kevin.Herron)\
**Post date:** [November 18, 2019, 7:51pm UTC](https://forum.inductiveautomation.com/t/adding-settings/30059/3 "2019-11-18T19:51:12Z")

</div>

Fortunately this is pretty easy because you just extend `RecordEditForm`:

```java
public class SettingsPage extends RecordEditForm {

    public SettingsPage(final IConfigPage configPage) {
        super(configPage, null, new LenientResourceModel("xopc.config.settings.paneltitle"),
            ((GatewayContext) Application.get()).getPersistenceInterface().find(
                XOPCSettingsRecord.META, 0L));
    }

    @Override
    public Pair<String, String> getMenuLocation() {
        return Pair.of(XOPCGatewayHook.OPCUA_CATEGORY.getName(), "settings");
    }

}

```

This is the UA module’s server settings page. There’s only ever one instance of this settings record, so it doesn’t even need to have a record passed in to the constructor.

---

<div class="post-metadata">

**Author:** ![jose](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/jose/32/11908_2.png) [@jose](https://forum.inductiveautomation.com/u/jose)\
**Post date:** [November 18, 2019, 8:04pm UTC](https://forum.inductiveautomation.com/t/adding-settings/30059/4 "2019-11-18T20:04:13Z")

</div>

> [@pturmel](#):
>
> getConfigPages()

There doesn't appear to be a getConfigPages() in my current Hook  
I'm on version 8.0.1  
There appears to be a getConfigPanels()  
Is this what I want?

---

<div class="post-metadata">

**Author:** ![Kevin.Herron](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/kevin.herron/32/7259_2.png) [@Kevin.Herron](https://forum.inductiveautomation.com/u/Kevin.Herron)\
**Post date:** [November 18, 2019, 8:06pm UTC](https://forum.inductiveautomation.com/t/adding-settings/30059/5 "2019-11-18T20:06:41Z")

</div>

Ah, it changed a bit in 8.0.

Check out this example: [https://github.com/inductiveautomation/ignition-sdk-examples/tree/master/gateway-webpage](https://github.com/inductiveautomation/ignition-sdk-examples/tree/master/gateway-webpage)

---

<div class="post-metadata">

**Author:** ![pturmel](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pturmel/32/3295_2.png) [@pturmel](https://forum.inductiveautomation.com/u/pturmel)\
**Post date:** [November 18, 2019, 8:09pm UTC](https://forum.inductiveautomation.com/t/adding-settings/30059/6 "2019-11-18T20:09:43Z")

</div>

My mistake. My own v8 module I looked at overrides getConfigPanels(). And it was true for v7.9 as well.

---

<div class="post-metadata">

**Author:** ![jose](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/jose/32/11908_2.png) [@jose](https://forum.inductiveautomation.com/u/jose)\
**Post date:** [November 18, 2019, 8:25pm UTC](https://forum.inductiveautomation.com/t/adding-settings/30059/7 "2019-11-18T20:25:57Z")

</div>

Thanks @Kevin.Herron  
Trying to follow that example I have the following now  
In Hook:

```auto
@Override
    public List<ConfigCategory> getConfigCategories() {
        return Collections.singletonList(CONFIG_CATEGORY);
    }
	
	public static final ConfigCategory CONFIG_CATEGORY =
	        new ConfigCategory("WebSocket", "WebSocketHeader", 700);

	 public static final IConfigTab HCE_CONFIG_ENTRY = DefaultConfigTab.builder()
	            .category(CONFIG_CATEGORY)
	            .name("WebScocketSettings")
	            .i18n("WebSocketSettings")
	            .page(SettingsPage.class)
	            .build();
	
	 @Override
	    public List<? extends IConfigTab> getConfigPanels() {
		 return Collections.singletonList(
		            HCE_CONFIG_ENTRY
		        );
	 }

```

Along with the SettingsPage similar to what you suggested

```auto
public class SettingsPage extends RecordEditForm {

    /**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	public SettingsPage(final IConfigPage configPage) {
        super(configPage, null, new LenientResourceModel("xopc.config.settings.paneltitle"),
            ((GatewayContext) Application.get()).getPersistenceInterface().find(
            		WebSocketsRecord.META, 1L));
    }

    @Override
    public Pair<String, String> getMenuLocation() {
        return Pair.of("WebSocket", "WebScocketSettings");
    }

}

```

And I am getting this which is progress!  
 ![image](https://us1.discourse-cdn.com/inductiveautomation/original/2X/f/f076b8bda84aaa26d5ae55ed68c8bc4308a9096d.png)

But clicking on it just yields : Internal error

With the log having the following

> **Exception**
>
> ```auto
> org.apache.wicket.WicketRuntimeException: Can't instantiate page using constructor 'public com.inductiveautomation.ignition.gateway.web.pages.Config(org.apache.wicket.request.mapper.parameter.PageParameters)' and argument 'path=[WebSocket.WebScocketSettings]'. Might be it doesn't exist, may be it is not visible (public).
> 
> at org.apache.wicket.session.DefaultPageFactory.newPage(DefaultPageFactory.java:193)
> 
> at org.apache.wicket.session.DefaultPageFactory.newPage(DefaultPageFactory.java:98)
> 
> at org.apache.wicket.DefaultMapperContext.newPageInstance(DefaultMapperContext.java:137)
> 
> at org.apache.wicket.core.request.handler.PageProvider.resolvePageInstance(PageProvider.java:278)
> 
> at org.apache.wicket.core.request.handler.PageProvider.getPageInstance(PageProvider.java:166)
> 
> at org.apache.wicket.request.handler.render.PageRenderer.getPage(PageRenderer.java:78)
> 
> at org.apache.wicket.request.handler.render.WebPageRenderer.renderPage(WebPageRenderer.java:94)
> 
> at org.apache.wicket.request.handler.render.WebPageRenderer.respond(WebPageRenderer.java:244)
> 
> at org.apache.wicket.core.request.handler.RenderPageRequestHandler.respond(RenderPageRequestHandler.java:165)
> 
> at org.apache.wicket.request.cycle.RequestCycle$HandlerExecutor.respond(RequestCycle.java:814)
> 
> at org.apache.wicket.request.RequestHandlerStack.execute(RequestHandlerStack.java:64)
> 
> at org.apache.wicket.request.cycle.RequestCycle.execute(RequestCycle.java:253)
> 
> at org.apache.wicket.request.cycle.RequestCycle.processRequest(RequestCycle.java:210)
> 
> at org.apache.wicket.request.cycle.RequestCycle.processRequestAndDetach(RequestCycle.java:281)
> 
> at org.apache.wicket.protocol.http.WicketFilter.processRequest(WicketFilter.java:188)
> 
> at org.apache.wicket.protocol.http.WicketFilter.doFilter(WicketFilter.java:245)
> 
> at com.inductiveautomation.ignition.gateway.bootstrap.GatewayFilter.doFilter(GatewayFilter.java:74)
> 
> at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1629)
> 
> at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:533)
> 
> at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:143)
> 
> at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:548)
> 
> at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:132)
> 
> at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:190)
> 
> at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:1595)
> 
> at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:188)
> 
> at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1253)
> 
> at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:168)
> 
> at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:473)
> 
> at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:1564)
> 
> at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:166)
> 
> at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1155)
> 
> at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141)
> 
> at org.eclipse.jetty.server.handler.HandlerList.handle(HandlerList.java:61)
> 
> at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:132)
> 
> at org.eclipse.jetty.rewrite.handler.RewriteHandler.handle(RewriteHandler.java:335)
> 
> at org.eclipse.jetty.server.handler.HandlerList.handle(HandlerList.java:61)
> 
> at org.eclipse.jetty.server.handler.HandlerCollection.handle(HandlerCollection.java:126)
> 
> at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:132)
> 
> at org.eclipse.jetty.server.Server.handle(Server.java:530)
> 
> at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:347)
> 
> at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:256)
> 
> at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:279)
> 
> at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:102)
> 
> at org.eclipse.jetty.io.ChannelEndPoint$2.run(ChannelEndPoint.java:124)
> 
> at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.doProduce(EatWhatYouKill.java:247)
> 
> at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.produce(EatWhatYouKill.java:140)
> 
> at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.run(EatWhatYouKill.java:131)
> 
> at org.eclipse.jetty.util.thread.ReservedThreadExecutor$ReservedThread.run(ReservedThreadExecutor.java:382)
> 
> at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:708)
> 
> at org.eclipse.jetty.util.thread.QueuedThreadPool$2.run(QueuedThreadPool.java:626)
> 
> at java.base/java.lang.Thread.run(Unknown Source)
> 
> Caused by: java.lang.reflect.InvocationTargetException: null
> 
> at jdk.internal.reflect.GeneratedConstructorAccessor62.newInstance(Unknown Source)
> 
> at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source)
> 
> at java.base/java.lang.reflect.Constructor.newInstance(Unknown Source)
> 
> at org.apache.wicket.session.DefaultPageFactory.newPage(DefaultPageFactory.java:170)
> 
> ... 50 common frames omitted
> 
> Caused by: java.lang.RuntimeException: Unable to create config panel WebSocket.WebScocketSettings
> 
> at com.inductiveautomation.ignition.gateway.web.models.DefaultConfigTab.getPanel(DefaultConfigTab.java:99)
> 
> at com.inductiveautomation.ignition.gateway.web.pages.Config.(Config.java:109)
> 
> ... 54 common frames omitted
> 
> Caused by: java.lang.reflect.InvocationTargetException: null
> 
> at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
> 
> at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source)
> 
> at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source)
> 
> at java.base/java.lang.reflect.Constructor.newInstance(Unknown Source)
> 
> at com.inductiveautomation.ignition.gateway.web.models.DefaultConfigTab.getPanel(DefaultConfigTab.java:91)
> 
> ... 55 common frames omitted
> 
> Caused by: java.lang.ClassCastException: class com.inductiveautomation.ignition.gateway.web.IgnitionWebAppImpl cannot be cast to class com.inductiveautomation.ignition.gateway.model.GatewayContext (com.inductiveautomation.ignition.gateway.web.IgnitionWebAppImpl and com.inductiveautomation.ignition.gateway.model.GatewayContext are in unnamed module of loader 'app')
> 
> at com.jnjdodev.ignition.modules.websocket.SettingsPage.(SettingsPage.java:20)
> 
> ... 60 common frames omitted
> 
> ```

Any suggestions as to what I’m doing wrong? I’m trying to follow that example but I can’t seem to get past this point.

Thanks!

---

<div class="post-metadata">

**Author:** ![jose](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/jose/32/11908_2.png) [@jose](https://forum.inductiveautomation.com/u/jose)\
**Post date:** [November 18, 2019, 8:30pm UTC](https://forum.inductiveautomation.com/t/adding-settings/30059/8 "2019-11-18T20:30:59Z")

</div>

Correction, I see the error is that it wants IgnitionWebApp instead of GateWayContext which I’ve corrected.

New Error:

> **Exception**
>
> ```auto
> org.apache.wicket.WicketRuntimeException: Can't instantiate page using constructor 'public com.inductiveautomation.ignition.gateway.web.pages.Config(org.apache.wicket.request.mapper.parameter.PageParameters)' and argument 'path=[WebSocket.WebScocketSettings]'. Might be it doesn't exist, may be it is not visible (public).
> 
> at org.apache.wicket.session.DefaultPageFactory.newPage(DefaultPageFactory.java:193)
> 
> at org.apache.wicket.session.DefaultPageFactory.newPage(DefaultPageFactory.java:98)
> 
> at org.apache.wicket.DefaultMapperContext.newPageInstance(DefaultMapperContext.java:137)
> 
> at org.apache.wicket.core.request.handler.PageProvider.resolvePageInstance(PageProvider.java:278)
> 
> at org.apache.wicket.core.request.handler.PageProvider.getPageInstance(PageProvider.java:166)
> 
> at org.apache.wicket.request.handler.render.PageRenderer.getPage(PageRenderer.java:78)
> 
> at org.apache.wicket.request.handler.render.WebPageRenderer.renderPage(WebPageRenderer.java:94)
> 
> at org.apache.wicket.request.handler.render.WebPageRenderer.respond(WebPageRenderer.java:244)
> 
> at org.apache.wicket.core.request.handler.RenderPageRequestHandler.respond(RenderPageRequestHandler.java:165)
> 
> at org.apache.wicket.request.cycle.RequestCycle$HandlerExecutor.respond(RequestCycle.java:814)
> 
> at org.apache.wicket.request.RequestHandlerStack.execute(RequestHandlerStack.java:64)
> 
> at org.apache.wicket.request.cycle.RequestCycle.execute(RequestCycle.java:253)
> 
> at org.apache.wicket.request.cycle.RequestCycle.processRequest(RequestCycle.java:210)
> 
> at org.apache.wicket.request.cycle.RequestCycle.processRequestAndDetach(RequestCycle.java:281)
> 
> at org.apache.wicket.protocol.http.WicketFilter.processRequest(WicketFilter.java:188)
> 
> at org.apache.wicket.protocol.http.WicketFilter.doFilter(WicketFilter.java:245)
> 
> at com.inductiveautomation.ignition.gateway.bootstrap.GatewayFilter.doFilter(GatewayFilter.java:74)
> 
> at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1629)
> 
> at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:533)
> 
> at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:143)
> 
> at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:548)
> 
> at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:132)
> 
> at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:190)
> 
> at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:1595)
> 
> at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:188)
> 
> at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1253)
> 
> at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:168)
> 
> at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:473)
> 
> at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:1564)
> 
> at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:166)
> 
> at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1155)
> 
> at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141)
> 
> at org.eclipse.jetty.server.handler.HandlerList.handle(HandlerList.java:61)
> 
> at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:132)
> 
> at org.eclipse.jetty.rewrite.handler.RewriteHandler.handle(RewriteHandler.java:335)
> 
> at org.eclipse.jetty.server.handler.HandlerList.handle(HandlerList.java:61)
> 
> at org.eclipse.jetty.server.handler.HandlerCollection.handle(HandlerCollection.java:126)
> 
> at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:132)
> 
> at org.eclipse.jetty.server.Server.handle(Server.java:530)
> 
> at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:347)
> 
> at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:256)
> 
> at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:279)
> 
> at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:102)
> 
> at org.eclipse.jetty.io.ChannelEndPoint$2.run(ChannelEndPoint.java:124)
> 
> at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.doProduce(EatWhatYouKill.java:247)
> 
> at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.produce(EatWhatYouKill.java:140)
> 
> at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.run(EatWhatYouKill.java:131)
> 
> at org.eclipse.jetty.util.thread.ReservedThreadExecutor$ReservedThread.run(ReservedThreadExecutor.java:382)
> 
> at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:708)
> 
> at org.eclipse.jetty.util.thread.QueuedThreadPool$2.run(QueuedThreadPool.java:626)
> 
> at java.base/java.lang.Thread.run(Unknown Source)
> 
> Caused by: java.lang.reflect.InvocationTargetException: null
> 
> at jdk.internal.reflect.GeneratedConstructorAccessor62.newInstance(Unknown Source)
> 
> at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source)
> 
> at java.base/java.lang.reflect.Constructor.newInstance(Unknown Source)
> 
> at org.apache.wicket.session.DefaultPageFactory.newPage(DefaultPageFactory.java:170)
> 
> ... 50 common frames omitted
> 
> Caused by: java.lang.RuntimeException: Unable to create config panel WebSocket.WebScocketSettings
> 
> at com.inductiveautomation.ignition.gateway.web.models.DefaultConfigTab.getPanel(DefaultConfigTab.java:99)
> 
> at com.inductiveautomation.ignition.gateway.web.pages.Config.(Config.java:109)
> 
> ... 54 common frames omitted
> 
> Caused by: java.lang.reflect.InvocationTargetException: null
> 
> at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
> 
> at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source)
> 
> at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source)
> 
> at java.base/java.lang.reflect.Constructor.newInstance(Unknown Source)
> 
> at com.inductiveautomation.ignition.gateway.web.models.DefaultConfigTab.getPanel(DefaultConfigTab.java:91)
> 
> ... 55 common frames omitted
> 
> Caused by: java.lang.NullPointerException: null
> 
> at com.inductiveautomation.ignition.gateway.web.models.DirectRecordListModel.(DirectRecordListModel.java:46)
> 
> at com.inductiveautomation.ignition.gateway.web.models.CompoundRecordModel.(CompoundRecordModel.java:48)
> 
> at com.inductiveautomation.ignition.gateway.web.models.CompoundRecordModel.(CompoundRecordModel.java:41)
> 
> at com.inductiveautomation.ignition.gateway.web.components.RecordEditForm.(RecordEditForm.java:65)
> 
> at com.jnjdodev.ignition.modules.websocket.SettingsPage.(SettingsPage.java:21)
> 
> ... 60 common frames omitted
> 
> ```

Still investigating

---

<div class="post-metadata">

**Author:** ![Kevin.Herron](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/kevin.herron/32/7259_2.png) [@Kevin.Herron](https://forum.inductiveautomation.com/u/Kevin.Herron)\
**Post date:** [November 18, 2019, 8:31pm UTC](https://forum.inductiveautomation.com/t/adding-settings/30059/9 "2019-11-18T20:31:04Z")

</div>

The root cause is this:

```auto
Caused by: java.lang.ClassCastException: class com.inductiveautomation.ignition.gateway.web.IgnitionWebAppImpl cannot be cast to class com.inductiveautomation.ignition.gateway.model.GatewayContext (com.inductiveautomation.ignition.gateway.web.IgnitionWebAppImpl and com.inductiveautomation.ignition.gateway.model.GatewayContext are in unnamed module of loader 'app')

```

Copy the page from the example rather than the one I posted, which came from 7.9.

---

<div class="post-metadata">

**Author:** ![jose](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/jose/32/11908_2.png) [@jose](https://forum.inductiveautomation.com/u/jose)\
**Post date:** [November 18, 2019, 8:45pm UTC](https://forum.inductiveautomation.com/t/adding-settings/30059/10 "2019-11-18T20:45:30Z")

</div>

So now it’s having a hard time with my “Path” “WebSocket.WebScocketSettings”

```auto
org.apache.wicket.WicketRuntimeException: Can't instantiate page using constructor 'public com.inductiveautomation.ignition.gateway.web.pages.Config(org.apache.wicket.request.mapper.parameter.PageParameters)' and argument 'path=[WebSocket.WebScocketSettings]'. Might be it doesn't exist, may be it is not visible (public).

```

I see that’s what I’m passing to CONFIG\_CATEGORY

```auto
	public static final ConfigCategory CONFIG_CATEGORY =
	        new ConfigCategory("WebSocket", "WebScocketSettings", 700);

```

And then I’m using that in my CONFIG\_ENTRY

```auto
public static final IConfigTab HCE_CONFIG_ENTRY = DefaultConfigTab.builder()
	            .category(CONFIG_CATEGORY)
	            .name("WebScocketSettings")
	            .i18n("WebScocketSettings")
	            .page(SettingsPage.class)
	            .build();

```

It seems to be taking issue with that (some how) but I’m not sure I follow what it wants. Any pointers?  
Sorry in advance, If i’m missing something obvious

Here is my persistence class if it matters

```auto
package com.jnjdodev.ignition.modules.websocket;

import com.inductiveautomation.ignition.gateway.localdb.persistence.Category;
import com.inductiveautomation.ignition.gateway.localdb.persistence.IdentityField;
import com.inductiveautomation.ignition.gateway.localdb.persistence.IntField;
import com.inductiveautomation.ignition.gateway.localdb.persistence.PersistentRecord;
import com.inductiveautomation.ignition.gateway.localdb.persistence.RecordMeta;

import simpleorm.dataset.SFieldFlags;

public class WebSocketsRecord extends PersistentRecord {

	
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	public static final RecordMeta<WebSocketsRecord> META = new RecordMeta<>(
			WebSocketsRecord.class, "WebSocketsRecord").setNounKey("WebSocketsRecord.Noun")
            .setNounPluralKey("WebSocketsRecord.Noun.Plural");

	public static final IdentityField Id = new IdentityField(META);
	
	
	 public static final IntField WebSocketPort = new IntField(META, "WebSocketPort",
	            SFieldFlags.SMANDATORY).setDefault(23333);
	@Override
	public RecordMeta<?> getMeta() {
		// TODO Auto-generated method stub
		return META;

	}
	

	public void setPort(int port)
	{
		this.setInt(WebSocketPort, port);
	}
	
	public int getPort()
	{
		return this.getInt(WebSocketPort);
	}

	
}

```

---

<div class="post-metadata">

**Author:** ![paul-griffith](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/paul-griffith/32/37249_2.png) [@paul-griffith](https://forum.inductiveautomation.com/u/paul-griffith)\
**Post date:** [November 18, 2019, 9:10pm UTC](https://forum.inductiveautomation.com/t/adding-settings/30059/11 "2019-11-18T21:10:25Z")

</div>

Does your `SettingsPage` still have the public `IConfigPage` constructor?

```auto
	public SettingsPage(final IConfigPage configPage) {

```

---

<div class="post-metadata">

**Author:** ![jose](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/jose/32/11908_2.png) [@jose](https://forum.inductiveautomation.com/u/jose)\
**Post date:** [November 18, 2019, 9:11pm UTC](https://forum.inductiveautomation.com/t/adding-settings/30059/12 "2019-11-18T21:11:43Z")

</div>

Yes it does, should it not?

---

<div class="post-metadata">

**Author:** ![paul-griffith](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/paul-griffith/32/37249_2.png) [@paul-griffith](https://forum.inductiveautomation.com/u/paul-griffith)\
**Post date:** [November 18, 2019, 9:20pm UTC](https://forum.inductiveautomation.com/t/adding-settings/30059/13 "2019-11-18T21:20:30Z")

</div>

It should, but the error’s indicating that it doesn’t:

```auto
org.apache.wicket.WicketRuntimeException: Can't instantiate page using constructor 'public com.inductiveautomation.ignition.gateway.web.pages.Config(org.apache.wicket.request.mapper.parameter.PageParameters)' and argument 'path=[WebSocket.WebScocketSettings]'. Might be it doesn't exist, may be it is not visible (public).

```

Is it just a typo? You’ve got `"WebScocketSettings"` in a few code snippets.

---

<div class="post-metadata">

**Author:** ![jose](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/jose/32/11908_2.png) [@jose](https://forum.inductiveautomation.com/u/jose)\
**Post date:** [November 18, 2019, 9:22pm UTC](https://forum.inductiveautomation.com/t/adding-settings/30059/14 "2019-11-18T21:22:00Z")

</div>

Yeah it’s just a typo but a consistent Typo lol… I think (Double checking)

---

<div class="post-metadata">

**Author:** ![jose](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/jose/32/11908_2.png) [@jose](https://forum.inductiveautomation.com/u/jose)\
**Post date:** [November 18, 2019, 9:47pm UTC](https://forum.inductiveautomation.com/t/adding-settings/30059/15 "2019-11-18T21:47:32Z")

</div>

ok So I’ve double checked everything and still can’t figure it out. I’m gonna post my files one more time hoping someone can see what I’m missing.

SettingsPage.java  
I’m using LenientResourceModel(“xopc.config.settings.paneltitle”) from above not sure if that’s right or what exactly does it mean? Examples seems to have their own?

```auto
public class SettingsPage extends RecordEditForm {

    /**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	public static final Pair<String, String> MENU_LOCATION =
	        Pair.of(WebSocketGatewayHook.CONFIG_CATEGORY.getName(), "Settings");

	
	public SettingsPage(final IConfigPage configPage) {
        super(configPage, null, new LenientResourceModel("xopc.config.settings.paneltitle"),
            ((IgnitionWebApp) Application.get()).getContext().getPersistenceInterface().find(
            		WebSocketsRecord.META, 0L));
    }

    @Override
    public Pair<String, String> getMenuLocation() {
    	return MENU_LOCATION;
    }

}

```

My persistance Record

```auto
package com.jnjdodev.ignition.modules.websocket;

import com.inductiveautomation.ignition.gateway.localdb.persistence.Category;
import com.inductiveautomation.ignition.gateway.localdb.persistence.IdentityField;
import com.inductiveautomation.ignition.gateway.localdb.persistence.IntField;
import com.inductiveautomation.ignition.gateway.localdb.persistence.PersistentRecord;
import com.inductiveautomation.ignition.gateway.localdb.persistence.RecordMeta;

import simpleorm.dataset.SFieldFlags;

public class WebSocketsRecord extends PersistentRecord {

	
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	public static final RecordMeta<WebSocketsRecord> META = new RecordMeta<>(
			WebSocketsRecord.class, "WebSocketsRecord").setNounKey("WebSocketsRecord.Noun")
            .setNounPluralKey("WebSocketsRecord.Noun.Plural");

	public static final IdentityField Id = new IdentityField(META);
	
	
	 public static final IntField WebSocketPort = new IntField(META, "WebSocketPort",
	            SFieldFlags.SMANDATORY).setDefault(23333);
	@Override
	public RecordMeta<?> getMeta() {
		// TODO Auto-generated method stub
		return META;

	}
	

	public void setPort(int port)
	{
		this.setInt(WebSocketPort, port);
	}
	
	public int getPort()
	{
		return this.getInt(WebSocketPort);
	}
	
}

```

Hook class

```auto
public void setup(GatewayContext context) {
		// TODO Auto-generated method stub
		this.context = context; 
		try {
			this.context.getSchemaUpdater().updatePersistentRecords(WebSocketsRecord.META);
		    maybeCreateWebSocketSettings(context);
...

```

```auto
public void maybeCreateWebSocketSettings(GatewayContext context) {
        logger.trace("Attempting to create GitConnector Settings Record");
        try {
            WebSocketsRecord settingsRecord = context.getLocalPersistenceInterface().createNew(WebSocketsRecord.META);
            settingsRecord.setPort(23333);

            /*
             * This doesn't override existing settings, only replaces it with these if we didn't
             * exist already.
             */
            context.getSchemaUpdater().ensureRecordExists(settingsRecord);
        } catch (Exception e) {
 
        }

    }
@Override
    public List<ConfigCategory> getConfigCategories() {
        return Collections.singletonList(CONFIG_CATEGORY);
    }
	
	public static final ConfigCategory CONFIG_CATEGORY =
	        new ConfigCategory("WebSocket", "WebSocket", 700);

	 public static final IConfigTab HCE_CONFIG_ENTRY = DefaultConfigTab.builder()
	            .category(CONFIG_CATEGORY)
	            .name("Settings")
	            .i18n("WebSocket")
	            .page(SettingsPage.class)
	            .build();
	
	 @Override
	    public List<? extends IConfigTab> getConfigPanels() {
		 return Collections.singletonList(
		            HCE_CONFIG_ENTRY
		        );
	 }	

```

Getting this error when I click on the menu item

> **Exception**
>
> ```auto
> org.apache.wicket.WicketRuntimeException: Can't instantiate page using constructor 'public com.inductiveautomation.ignition.gateway.web.pages.Config(org.apache.wicket.request.mapper.parameter.PageParameters)' and argument 'path=[WebSocket.Settings]'. Might be it doesn't exist, may be it is not visible (public).
> 
> at org.apache.wicket.session.DefaultPageFactory.newPage(DefaultPageFactory.java:193)
> 
> at org.apache.wicket.session.DefaultPageFactory.newPage(DefaultPageFactory.java:98)
> 
> at org.apache.wicket.DefaultMapperContext.newPageInstance(DefaultMapperContext.java:137)
> 
> at org.apache.wicket.core.request.handler.PageProvider.resolvePageInstance(PageProvider.java:278)
> 
> at org.apache.wicket.core.request.handler.PageProvider.getPageInstance(PageProvider.java:166)
> 
> at org.apache.wicket.request.handler.render.PageRenderer.getPage(PageRenderer.java:78)
> 
> at org.apache.wicket.request.handler.render.WebPageRenderer.renderPage(WebPageRenderer.java:94)
> 
> at org.apache.wicket.request.handler.render.WebPageRenderer.respond(WebPageRenderer.java:244)
> 
> at org.apache.wicket.core.request.handler.RenderPageRequestHandler.respond(RenderPageRequestHandler.java:165)
> 
> at org.apache.wicket.request.cycle.RequestCycle$HandlerExecutor.respond(RequestCycle.java:814)
> 
> at org.apache.wicket.request.RequestHandlerStack.execute(RequestHandlerStack.java:64)
> 
> at org.apache.wicket.request.cycle.RequestCycle.execute(RequestCycle.java:253)
> 
> at org.apache.wicket.request.cycle.RequestCycle.processRequest(RequestCycle.java:210)
> 
> at org.apache.wicket.request.cycle.RequestCycle.processRequestAndDetach(RequestCycle.java:281)
> 
> at org.apache.wicket.protocol.http.WicketFilter.processRequest(WicketFilter.java:188)
> 
> at org.apache.wicket.protocol.http.WicketFilter.doFilter(WicketFilter.java:245)
> 
> at com.inductiveautomation.ignition.gateway.bootstrap.GatewayFilter.doFilter(GatewayFilter.java:74)
> 
> at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1629)
> 
> at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:533)
> 
> at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:143)
> 
> at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:548)
> 
> at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:132)
> 
> at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:190)
> 
> at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:1595)
> 
> at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:188)
> 
> at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1253)
> 
> at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:168)
> 
> at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:473)
> 
> at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:1564)
> 
> at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:166)
> 
> at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1155)
> 
> at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141)
> 
> at org.eclipse.jetty.server.handler.HandlerList.handle(HandlerList.java:61)
> 
> at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:132)
> 
> at org.eclipse.jetty.rewrite.handler.RewriteHandler.handle(RewriteHandler.java:335)
> 
> at org.eclipse.jetty.server.handler.HandlerList.handle(HandlerList.java:61)
> 
> at org.eclipse.jetty.server.handler.HandlerCollection.handle(HandlerCollection.java:126)
> 
> at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:132)
> 
> at org.eclipse.jetty.server.Server.handle(Server.java:530)
> 
> at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:347)
> 
> at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:256)
> 
> at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:279)
> 
> at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:102)
> 
> at org.eclipse.jetty.io.ChannelEndPoint$2.run(ChannelEndPoint.java:124)
> 
> at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.doProduce(EatWhatYouKill.java:247)
> 
> at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.produce(EatWhatYouKill.java:140)
> 
> at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.run(EatWhatYouKill.java:131)
> 
> at org.eclipse.jetty.util.thread.ReservedThreadExecutor$ReservedThread.run(ReservedThreadExecutor.java:382)
> 
> at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:708)
> 
> at org.eclipse.jetty.util.thread.QueuedThreadPool$2.run(QueuedThreadPool.java:626)
> 
> at java.base/java.lang.Thread.run(Unknown Source)
> 
> Caused by: java.lang.reflect.InvocationTargetException: null
> 
> at jdk.internal.reflect.GeneratedConstructorAccessor62.newInstance(Unknown Source)
> 
> at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source)
> 
> at java.base/java.lang.reflect.Constructor.newInstance(Unknown Source)
> 
> at org.apache.wicket.session.DefaultPageFactory.newPage(DefaultPageFactory.java:170)
> 
> ... 50 common frames omitted
> 
> Caused by: java.lang.RuntimeException: Unable to create config panel WebSocket.Settings
> 
> at com.inductiveautomation.ignition.gateway.web.models.DefaultConfigTab.getPanel(DefaultConfigTab.java:99)
> 
> at com.inductiveautomation.ignition.gateway.web.pages.Config.(Config.java:109)
> 
> ... 54 common frames omitted
> 
> Caused by: java.lang.reflect.InvocationTargetException: null
> 
> at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
> 
> at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source)
> 
> at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source)
> 
> at java.base/java.lang.reflect.Constructor.newInstance(Unknown Source)
> 
> at com.inductiveautomation.ignition.gateway.web.models.DefaultConfigTab.getPanel(DefaultConfigTab.java:91)
> 
> ... 55 common frames omitted
> 
> Caused by: java.lang.NullPointerException: null
> 
> at com.inductiveautomation.ignition.gateway.web.models.DirectRecordListModel.(DirectRecordListModel.java:46)
> 
> at com.inductiveautomation.ignition.gateway.web.models.CompoundRecordModel.(CompoundRecordModel.java:48)
> 
> at com.inductiveautomation.ignition.gateway.web.models.CompoundRecordModel.(CompoundRecordModel.java:41)
> 
> at com.inductiveautomation.ignition.gateway.web.components.RecordEditForm.(RecordEditForm.java:65)
> 
> at com.jnjdodev.ignition.modules.websocket.SettingsPage.(SettingsPage.java:25)
> 
> ... 60 common frames omitted
> 
> ```

Lastly the menu Item seems to be kinda weird with a bunch of question marks around it?  
 ![image](https://us1.discourse-cdn.com/inductiveautomation/original/2X/2/24e1b101eaec93f3471962420d7952826537e348.png)

Any ideas are really appreciated!

I"ve managed to write an entire working module but can’t figure out the Settings page LoL!

Thanks again~!

---

<div class="post-metadata">

**Author:** ![pturmel](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pturmel/32/3295_2.png) [@pturmel](https://forum.inductiveautomation.com/u/pturmel)\
**Post date:** [November 18, 2019, 10:57pm UTC](https://forum.inductiveautomation.com/t/adding-settings/30059/16 "2019-11-18T22:57:06Z")

</div>

The question marks are because you haven’t loaded a bundle of translation properties for the resource keys you have provided. (Similar to the properties specific to the settings record, which get autoloaded.) Look at the BundleUtil class.

---

<div class="post-metadata">

**Author:** ![jose](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/jose/32/11908_2.png) [@jose](https://forum.inductiveautomation.com/u/jose)\
**Post date:** [November 19, 2019, 1:43pm UTC](https://forum.inductiveautomation.com/t/adding-settings/30059/17 "2019-11-19T13:43:07Z")

</div>

Thanks @pturmel I’ll give that a shot

---

<div class="post-metadata">

**Author:** ![jose](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/jose/32/11908_2.png) [@jose](https://forum.inductiveautomation.com/u/jose)\
**Post date:** [November 20, 2019, 2:54pm UTC](https://forum.inductiveautomation.com/t/adding-settings/30059/18 "2019-11-20T14:54:10Z")

</div>

Thanks @pturmel that fixed all my issues
