2 server instances using the same database server

Hi,

We have already an online servoy server running and its postgres database server. I would like to have another servoy server instance running but accessing the same database as the current one. We will deploy different versions of the solution we work at on each servoy server, so each server must have its own repository.

What are the recommendations?

Thanks,
Bogdan.

Hi Bogdan,

Shouldn’t really be a problem if you use database sequences/identities.
If you use Servoy sequences however you can not do this. Servoy sequences are stored in the repository database (or workspace when using Developer) and managed in 1 single instance. Using multiple instances (or even Developer and Server) then you will get into trouble because the sequences will get out of sync and you get duplicate PK errors.

Hope this helps.

Hello, thanks for the info. I’m using servoy sequences now. But can I change them to db seq or db identity without any problems for the solution? What option to use from those two?

Hi Bogdan,

That depends on the backend database.
If you use PostgreSQL and you defined your tables to use bigserials (bigint with a sequence) then Servoy will make it a dbidentity. Otherwise you need to make it a db sequence and fill in the sequence name.
Of course you need to define sequences (per table), unless you use bigserial then those will be created for you.

Hi Robert,

I use PostgreSQL. The primary key in each table are INTEGER with servoy seq, as I said. Where can I see if they are bigserials?

Now, regarding the db identity and db seq, can I use any of these? Which one can accept greater values? According with what you said earlier, it seems that db identity is better. Please correct me if I’m wrong.

Can I just change the sequence type for each table and it will make the switch properly after deploy?

Thanks,
Bogdan.

udrescu_bogdan:
Hi Robert,

I use PostgreSQL. The primary key in each table are INTEGER with servoy seq, as I said. Where can I see if they are bigserials?

If they are integers then they can be ‘serials’. Bigserials are always bigints.
You can see what it is by connecting to the database using PgAdmin, select the table in the tree and check the SQL pane. This will tell you if it’s a Serial or a BigSerial (or not).
But again, this (Big)Serial datatype is not a real datatype. It’s an (Big) Integer with a database sequence attached. So you can also simply check if it calls a sequence in the default value. This usually looks like nextval(‘mysequencename_seq’::regclass).

udrescu_bogdan:
Now, regarding the db identity and db seq, can I use any of these? Which one can accept greater values? According with what you said earlier, it seems that db identity is better. Please correct me if I’m wrong.
It depends on the datatype (big integer vs integer) if it can accept greater values. Anyway, if you use (big)serials you can simply use db identities.

udrescu_bogdan:
Can I just change the sequence type for each table and it will make the switch properly after deploy?

Servoy server will always read the schema at startup and use dbidenties when it finds you are using db sequences (or otherwise Servoy sequences), unless you tell it otherwise. That is what the “Override existing sequence type definitions (in repository) with the sequence types contained in the import file.” checkbox is about in the Servoy Admin page.
I prefer to use that option for the first time I import a solution so I am certain it uses the sequences I want it to use.

Hope this helps.

I connected with pgadmin but in the SQL tab from the properties of a table I see nothing, except this text: “-- nothing to change”

One more thing then:

In many places of the app I create a newRecord on a foundset and then I use the id of the record to set it on another foundset. Then I save! Is this going to work well even the autoSave is set on false and databaseManager.saveData() is called later?

Hi again,

I skipped one detail last time!

The USERS! I need the same users database for both servers. Also new users are created from within the solution, by other users who have the rights for this. So when a client use the app from one server and creates a user, that user must be available also on the other server as well.

How can I solve this?

Thanks,
Bogdan.

I tried to change to db identities, but got an warning when deploy that I should check with the database server if the identity columns exists, or something like that. I don’t remember now. I’ll try again to see the message, but anyway, when creating a record, I received again an error in servoy. This I can see it in the log:

2011-10-26 06:38:22,131 ERROR [http-8080-1] com.servoy.j2db.util.Debug - ERROR: column "dbidentvalue1376617526" does not exist
  Position: 166
2011-10-26 06:38:22,131 ERROR [http-8080-1] com.servoy.j2db.util.Debug - Throwable
org.mozilla.javascript.WrappedException: Wrapped com.servoy.j2db.dataprocessing.DataException: ERROR: column "dbidentvalue1376617526" does not exist
  Position: 166 (loadDS#45)
	at org.mozilla.javascript.Context.throwAsScriptRuntimeEx(Context.java:1828)
	at org.mozilla.javascript.MemberBox.invoke(MemberBox.java:199)
	at org.mozilla.javascript.NativeJavaMethod.call(NativeJavaMethod.java:353)
	at org.mozilla.javascript.Interpreter.interpretLoop(Interpreter.java:3666)
	at script.loadDS(loadDS:45)
	at script.resetBookingsAvailability(resetBookingsAvailability:1084)
	at script.resetAvailability(resetAvailability:1074)
	at script.onPlaneChange(onPlaneChange:209)
	at script.populatePlanes(populatePlanes:194)
	at script.onShowForm(onShowForm:371)
	at org.mozilla.javascript.Interpreter.interpret(Interpreter.java:2680)
	at org.mozilla.javascript.InterpretedFunction.call(InterpretedFunction.java:166)
	at com.servoy.j2db.scripting.ScriptEngine.executeFunction(ScriptEngine.java:476)
	at com.servoy.j2db.FormController.executeFunction(FormController.java:3982)
	at com.servoy.j2db.FormController.executeFormMethod(FormController.java:4296)
	at com.servoy.j2db.FormController.executeOnShowMethod(FormController.java:4175)
	at com.servoy.j2db.FormController.access$15(FormController.java:4166)
	at com.servoy.j2db.FormController$3.run(FormController.java:3045)
	at com.servoy.j2db.server.headlessclient.WebClient.invokeLater(WebClient.java:528)
	at com.servoy.j2db.util.Utils.invokeLater(Utils.java:1782)
	at com.servoy.j2db.server.headlessclient.dataui.WebTabPanel.setActiveTabPanel(WebTabPanel.java:396)
	at com.servoy.j2db.server.headlessclient.dataui.WebTabPanel.js_setTabIndex(WebTabPanel.java:1105)
	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.mozilla.javascript.MemberBox.invoke(MemberBox.java:179)
	at org.mozilla.javascript.JavaMembers.put(JavaMembers.java:178)
	at org.mozilla.javascript.NativeJavaObject.put(NativeJavaObject.java:141)
	at org.mozilla.javascript.ScriptableObject.putProperty(ScriptableObject.java:1768)
	at org.mozilla.javascript.ScriptRuntime.setObjectProp(ScriptRuntime.java:1532)
	at org.mozilla.javascript.ScriptRuntime.setObjectProp(ScriptRuntime.java:1520)
	at org.mozilla.javascript.Interpreter.interpretLoop(Interpreter.java:3355)
	at script.addReservation(addReservation:167)
	at script.onAddReservation(onAddReservation:27)
	at org.mozilla.javascript.Interpreter.interpret(Interpreter.java:2680)
	at org.mozilla.javascript.InterpretedFunction.call(InterpretedFunction.java:166)
	at org.mozilla.javascript.ContextFactory.doTopCall(ContextFactory.java:387)
	at org.mozilla.javascript.ScriptRuntime.doTopCall(ScriptRuntime.java:3135)
	at org.mozilla.javascript.InterpretedFunction.call(InterpretedFunction.java:165)
	at com.servoy.j2db.scripting.ScriptEngine.executeFunction(ScriptEngine.java:476)
	at com.servoy.j2db.FormController.executeFunction(FormController.java:3982)
	at com.servoy.j2db.FormController.executeFunction(FormController.java:3870)
	at com.servoy.j2db.FormController.executeFunction(FormController.java:3792)
	at com.servoy.j2db.FormController$ScriptExecuter.executeFunction(FormController.java:3647)
	at com.servoy.j2db.ui.BaseEventExecutor.fireEventCommand(BaseEventExecutor.java:272)
	at com.servoy.j2db.ui.BaseEventExecutor.fireActionCommand(BaseEventExecutor.java:217)
	at com.servoy.j2db.server.headlessclient.dataui.WebEventExecutor.onEvent(WebEventExecutor.java:364)
	at com.servoy.j2db.server.headlessclient.dataui.WebEventExecutor$2.onEvent(WebEventExecutor.java:168)
	at org.apache.wicket.ajax.AjaxEventBehavior.respond(AjaxEventBehavior.java:177)
	at org.apache.wicket.ajax.AbstractDefaultAjaxBehavior.onRequest(AbstractDefaultAjaxBehavior.java:302)
	at org.apache.wicket.request.target.component.listener.BehaviorRequestTarget.processEvents(BehaviorRequestTarget.java:157)
	at org.apache.wicket.request.AbstractRequestCycleProcessor.processEvents(AbstractRequestCycleProcessor.java:92)
	at org.apache.wicket.RequestCycle.processEventsAndRespond(RequestCycle.java:1252)
	at org.apache.wicket.RequestCycle.step(RequestCycle.java:1331)
	at org.apache.wicket.RequestCycle.steps(RequestCycle.java:1438)
	at org.apache.wicket.RequestCycle.request(RequestCycle.java:546)
	at org.apache.wicket.protocol.http.WicketFilter.doGet(WicketFilter.java:486)
	at com.servoy.j2db.server.servlets.Zl.doGet(Zl.java:5)
	at org.apache.wicket.protocol.http.WicketServlet.doGet(WicketServlet.java:138)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:617)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128)
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
	at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:567)
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:293)
	at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:849)
	at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:583)
	at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:454)
	at java.lang.Thread.run(Thread.java:680)
Caused by: com.servoy.j2db.dataprocessing.DataException: ERROR: column "dbidentvalue1376617526" does not exist
  Position: 166
	at com.servoy.j2db.dblayer.Zb.Za(Zb.java:116)
	at com.servoy.j2db.server.Zc.Zo.Za(Zo.java:1333)
	at com.servoy.j2db.dataprocessing.Zu.Za(Zu.java:429)
	at com.servoy.j2db.dataprocessing.Zu.Za(Zu.java:332)
	at com.servoy.j2db.dataprocessing.Zu.performQuery(Zu.java:253)
	at com.servoy.j2db.dataprocessing.FoundSet.loadByQuery(FoundSet.java:1451)
	at com.servoy.j2db.dataprocessing.FoundSet.js_loadRecords(FoundSet.java:987)
	at sun.reflect.GeneratedMethodAccessor408.invoke(Unknown Source)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
	at java.lang.reflect.Method.invoke(Method.java:597)
	at org.mozilla.javascript.MemberBox.invoke(MemberBox.java:179)
	... 65 more

Then I tried with sequences, but they started from 1 instead of the maximum id in the table.

I read that the db identities are managed fully by the database while the db sequences must have a function or something, and from this reason I would prefer the identities, I don’t want to worry for them.

And then the users problem I wrote about in the previous post. How can the same users be managed by 2 servers?

Hi guys. No one ever done a load balancing with servoy until now?

I did :). Not in a production environment though. There is someone (at least) that actually did it in production as far as I know.
Why do you need different solution versions on the two servers?

I would suggest using clustering; that will allow you to continue using servoy sequences, also it will take care (make it as if you are running one server) of data broadcasting, locking and other aspects that would be unpleasant if you were running two separate application servers (including users). Still clustering was meant so that more application servers run as one, so the repository and databases used need to be exactly the same for all servers. Maybe you could still run separate versions of your solution somehow … try doing it in the same application server to see if it is not too complicated. (try taking advantage of clean import). Anyway I never tried this before.

Clustering would ease what I said above, but you must realize it needs some set-up work. Here is what you need to set it up:
Clustering Servoy Application Servers
Load balancing

If you decide to go ahead with clustering but get stuck when following wiki, let us know.

Hello Andrei,

It’s nice to hear that at least you did it. I’ll have a look on those things. But I really want to separate the database from servoy. In case I want to build another app on top of the database, I need an independent database.
Does the clustering solve also the users problem?

I’ll keep you informed. Thanks a lot!
Bogdan.

You can always use a separate database for the Repository and separate database(s) for your data.
That is true with and without clustering.

Of course you can also replace Servoy Sequences with Database stuff as mentioned in the posts above. No problem from Servoy’s point of view.
Just do what you must with the db admin tools and then make sure the changed columns are marked appropriately in Servoy.