Thanks for your help and I've no disagreement with your frank advice. I am on the bottom end of a learning curve, one which I am working hard to climb.
Just one question, about the domain service for each domain object, this seems sensible for top-level objects, but isn't it contrary to good OO modelling to do it for every domain object? DDD has the aggregates concept, which if I understand means a hierarchy with the top level objects managing the lower level ones. For example in this scenario, it makes sense for an Activity to 'register' a Participant and in doing so add a Participation to its participants collection. Having a participation repository domain service just confuses this. Participation at the database level is a join table between Activity and Participant for a many-to-many relationship, but it also holds data. What I haven't done is model this properly in terms of these register and unregister 'messages' (methods) for the Participant to use on Activity, which I will now do, with some tests. But the right pattern to use is still unclear. On Thu, Sep 3, 2015 at 5:23 AM, Jeroen van der Wal <[email protected]> wrote: > Hi Stephen, > > I did some fixes on your code [1] but stopped at a certain point because > your code doesn't contain any unit test, integration tests or fixture > scripts and that makes development very tedious. I recommend you start > eating away this huge amount of technical debt and as a result of this you > will encounter the bugs in your code that are hunting you. You might want > to check out Estatio as starting point [2]. > > Some specific observations: > - I never use interfaces to describe domain objects; it leaves you with two > artefacts to maintain [3] > - don't use getXx methods for actions [4] > - use JDO to manage collections [5]. There are useful IDE templates which > greatly improves productivity [6] > - create a domain service for each domain object that acts a a repository > and factory and thus handles all database interaction. And write > integration tests for each of it's members! > > HTH > > Cheers, > Jeroen > > [1] https://github.com/jcvanderwal/isis-chats/tree/fixup > [2] https://github.com/estatio/estatio > [3] > > https://github.com/Stephen-Cameron-Data-Services/isis-chats/blob/master/dom/src/main/java/au/com/scds/chats/dom/module/activity/Activity.java#L11 > [4] > > https://github.com/Stephen-Cameron-Data-Services/isis-chats/blob/master/dom/src/main/java/au/com/scds/chats/dom/module/activity/AbstractActivity.java#L103 > [5] http://isis.apache.org/guides/ug.html#4.5.-entity-relationships > [6] http://isis.apache.org/guides/cg.html#_cg_ide-templates > > > On 2 September 2015 at 15:48, Stephen Cameron <[email protected]> > wrote: > > > However, after fixing that I now see the other error I was getting > > yesterday :( > > > > Class "au.com.scds.chats.dom.module.activity.AbstractActivity" has > > collection field "participationList" and this has no mapping in the table > > for the element class > > "au.com.scds.chats.dom.module.participant.Participation" owner field > > "activity" > > > > I have the following in AbstractActivity: > > > > @Persistent(mappedBy="activity") > > private List<Participation> participationList = new > > ArrayList<Participation>(); > > > > And the property 'activity' is in Participation, > > > > private Activity activity; > > > > @Column(allowsNull = "false") > > @Property(hidden = Where.EVERYWHERE) > > @MemberOrder(sequence = "3") > > public Activity getActivity() { > > return this.activity; > > } > > > > This time I've not made any assumptions, but will be proven wrong again > no > > doubt. > > > > I've pushed my changes into Github for the foreign key issue. > > > > On Wed, Sep 2, 2015 at 11:18 PM, Stephen Cameron < > > [email protected] > > > wrote: > > > > > Its obvious now, sorry for wasting your time. getProvider is in parent > > and > > > child. > > > > > > On Wed, Sep 2, 2015 at 11:01 PM, Stephen Cameron < > > > [email protected]> wrote: > > > > > >> OK, I pushed the current versions to Github. > > >> > > >> https://github.com/Stephen-Cameron-Data-Services/isis-chats.git > > >> > > >> If you start the app and create a new Activity (an ActivityEvent > object) > > >> from the main menu you will see the error. I have no tests independant > > of > > >> the webapp sorry. > > >> > > >> I'll have to call it a day here soon, but it would be great if you > could > > >> have a quick look, just to see if something pops out for you that I am > > >> missing. It must be something about that relationship specifically, > its > > the > > >> only one duplicated. > > >> > > >> > > >> On Wed, Sep 2, 2015 at 10:51 PM, Stephen Cameron < > > >> [email protected]> wrote: > > >> > > >>> I'll check in what I have now, but the issue is simply that an > > identical > > >>> foreign key is being created twice for some reason. I thought it > might > > be > > >>> an artifact of there being two child tables. It had me confused as I > > didn't > > >>> change much to what was working, including the relationship Activity > to > > >>> Provider. > > >>> > > >>> Here is the log, you can see activity_FK3 and activity_FK7 are the > > same: > > >>> > > >>> 22:16:33,740 [Schema 275150920@qtp-1846345504-0 > DEBUG] > > >>> Execution Time = 1 ms > > >>> 22:16:33,743 [Schema 275150920@qtp-1846345504-0 > DEBUG] > > >>> Creating foreign key constraint : "activity_FK3" in catalog "" schema > > "" > > >>> 22:16:33,743 [Schema 275150920@qtp-1846345504-0 > DEBUG] > > >>> ALTER TABLE "activity" ADD CONSTRAINT "activity_FK3" FOREIGN KEY > > >>> ("provider_id_OID") REFERENCES "Provider" ("id") > > >>> 22:16:33,745 [Schema 275150920@qtp-1846345504-0 > DEBUG] > > >>> Execution Time = 2 ms > > >>> 22:16:33,745 [Schema 275150920@qtp-1846345504-0 > DEBUG] > > >>> Creating foreign key constraint : "activity_FK4" in catalog "" schema > > "" > > >>> 22:16:33,745 [Schema 275150920@qtp-1846345504-0 > DEBUG] > > >>> ALTER TABLE "activity" ADD CONSTRAINT "activity_FK4" FOREIGN KEY > > >>> ("region_region_OID") REFERENCES "Region" ("region") > > >>> 22:16:33,746 [Schema 275150920@qtp-1846345504-0 > DEBUG] > > >>> Execution Time = 1 ms > > >>> 22:16:33,746 [Schema 275150920@qtp-1846345504-0 > DEBUG] > > >>> Creating foreign key constraint : "activity_FK1" in catalog "" schema > > "" > > >>> 22:16:33,746 [Schema 275150920@qtp-1846345504-0 > DEBUG] > > >>> ALTER TABLE "activity" ADD CONSTRAINT "activity_FK1" FOREIGN KEY > > >>> ("activityType_name_OID") REFERENCES "ActivityType" ("name") > > >>> 22:16:33,747 [Schema 275150920@qtp-1846345504-0 > DEBUG] > > >>> Execution Time = 1 ms > > >>> 22:16:33,747 [Schema 275150920@qtp-1846345504-0 > DEBUG] > > >>> Creating foreign key constraint : "activity_FK2" in catalog "" schema > > "" > > >>> 22:16:33,748 [Schema 275150920@qtp-1846345504-0 > DEBUG] > > >>> ALTER TABLE "activity" ADD CONSTRAINT "activity_FK2" FOREIGN KEY > > >>> ("location_location_OID") REFERENCES "Location" ("location") > > >>> 22:16:33,749 [Schema 275150920@qtp-1846345504-0 > DEBUG] > > >>> Execution Time = 1 ms > > >>> 22:16:33,749 [Schema 275150920@qtp-1846345504-0 > DEBUG] > > >>> Creating foreign key constraint : "activity_FK7" in catalog "" schema > > "" > > >>> 22:16:33,749 [Schema 275150920@qtp-1846345504-0 > DEBUG] > > >>> ALTER TABLE "activity" ADD CONSTRAINT "activity_FK7" FOREIGN KEY > > >>> ("provider_id_OID") REFERENCES "Provider" ("id") > > >>> 22:16:33,761 [Schema 275150920@qtp-1846345504-0 > DEBUG] > > >>> Creating foreign key constraint : "activity_FK5" in catalog "" schema > > "" > > >>> 22:16:33,761 [Schema 275150920@qtp-1846345504-0 > DEBUG] > > >>> ALTER TABLE "activity" ADD CONSTRAINT "activity_FK5" FOREIGN KEY > > >>> ("parent_RecurringActivity_ID_OID") REFERENCES "RecurringActivity" > > >>> ("RecurringActivity_ID") > > >>> 22:16:33,763 [Schema 275150920@qtp-1846345504-0 > DEBUG] > > >>> Execution Time = 2 ms > > >>> 22:16:33,763 [Schema 275150920@qtp-1846345504-0 > DEBUG] > > >>> Creating foreign key constraint : "activity_FK6" in catalog "" schema > > "" > > >>> 22:16:33,763 [Schema 275150920@qtp-1846345504-0 > DEBUG] > > >>> ALTER TABLE "activity" ADD CONSTRAINT "activity_FK6" FOREIGN KEY > > >>> ("parentActivity_RecurringActivity_ID_OID") REFERENCES > > "RecurringActivity" > > >>> ("RecurringActivity_ID") > > >>> 22:16:33,765 [Schema 275150920@qtp-1846345504-0 > DEBUG] > > >>> Execution Time = 2 ms > > >>> > > >>> On Wed, Sep 2, 2015 at 10:42 PM, Jeroen van der Wal < > > [email protected] > > >>> > wrote: > > >>> > > >>>> Hi Stephen, you're leaving so much to guess. Can you put your code > or > > >>>> part > > >>>> of it on github? > > >>>> > > >>>> Cheers, > > >>>> > > >>>> Jeroen > > >>>> > > >>>> On 2 September 2015 at 13:38, Stephen Cameron < > > >>>> [email protected]> > > >>>> wrote: > > >>>> > > >>>> > Hi again, > > >>>> > > > >>>> > I am back to trying to resolve my original issues, before being > > >>>> sidetracked > > >>>> > with the abstract class problem. I've not yet got a simple test > case > > >>>> for > > >>>> > this, but will create one if no-one can give me a solution strait > > off. > > >>>> > > > >>>> > It seems as if foreign keys are being created twice. The stack > trace > > >>>> is > > >>>> > below. > > >>>> > > > >>>> > I have 4 tables now two abstract and two concrete, one abstract > > class > > >>>> > extends the other and the two concrete classes extend the second > > >>>> abstract > > >>>> > ctype. > > >>>> > > > >>>> > These are: > > >>>> > > > >>>> > @PersistenceCapable() > > >>>> > @Inheritance(strategy = InheritanceStrategy.SUBCLASS_TABLE) > > >>>> > @Discriminator(strategy=DiscriminatorStrategy.CLASS_NAME, > > >>>> column="class") > > >>>> > public abstract class AbstractChatsDomainEntity {...} > > >>>> > > > >>>> > @PersistenceCapable(table="activity") > > >>>> > @Inheritance(strategy = InheritanceStrategy.NEW_TABLE) > > >>>> > @Discriminator(strategy=DiscriminatorStrategy.CLASS_NAME, > > >>>> column="class") > > >>>> > public abstract class AbstractActivity extends > > >>>> AbstractChatsDomainEntity > > >>>> > implements Activity, Comparable<Activity> {...} > > >>>> > > > >>>> > @PersistenceCapable() > > >>>> > @Inheritance(strategy = InheritanceStrategy.SUPERCLASS_TABLE) > > >>>> > @DomainObject(objectType = "ACTIVITY") > > >>>> > @DomainObjectLayout(bookmarking = BookmarkPolicy.AS_ROOT) > > >>>> > public class ActivityEvent extends AbstractActivity implements > > >>>> > CalendarEventable {...} > > >>>> > > > >>>> > @PersistenceCapable() > > >>>> > @Inheritance(strategy = InheritanceStrategy.SUPERCLASS_TABLE) > > >>>> > @DomainObject(objectType = "RECURRING_ACTIVITY") > > >>>> > @DomainObjectLayout(bookmarking = BookmarkPolicy.AS_ROOT) > > >>>> > public class RecurringActivity extends AbstractActivity {...} > > >>>> > > > >>>> > I'll remove one of these concrete classes temporarily and see what > > >>>> happens. > > >>>> > > > >>>> > 21:17:28,766 [Datastore 421163163@qtp-899376395-0 > > >>>> ERROR] An > > >>>> > exception was thrown while adding/validating class(es) : a FOREIGN > > KEY > > >>>> > constraint already exists on the set of columns: "activity_FK7" in > > >>>> > statement [ALTER TABLE "activity" ADD CONSTRAINT "activity_FK7" > > >>>> FOREIGN KEY > > >>>> > ("provider_id_OID") REFERENCES "Provider" ("id") ] > > >>>> > java.sql.SQLSyntaxErrorException: a FOREIGN KEY constraint already > > >>>> exists > > >>>> > on the set of columns: "activity_FK7" in statement [ALTER TABLE > > >>>> "activity" > > >>>> > ADD CONSTRAINT "activity_FK7" FOREIGN KEY ("provider_id_OID") > > >>>> REFERENCES > > >>>> > "Provider" ("id") ] > > >>>> > at org.hsqldb.jdbc.JDBCUtil.sqlException(Unknown Source) > > >>>> > at org.hsqldb.jdbc.JDBCUtil.sqlException(Unknown Source) > > >>>> > at org.hsqldb.jdbc.JDBCStatement.fetchResult(Unknown Source) > > >>>> > at org.hsqldb.jdbc.JDBCStatement.execute(Unknown Source) > > >>>> > at > > >>>> > > > >>>> > > > >>>> > > > org.datanucleus.store.rdbms.datasource.dbcp.DelegatingStatement.execute(DelegatingStatement.java:246) > > >>>> > at > > >>>> > > > >>>> > > > >>>> > > > org.datanucleus.store.rdbms.datasource.dbcp.DelegatingStatement.execute(DelegatingStatement.java:246) > > >>>> > at > > >>>> > > > >>>> > > > >>>> > > > org.datanucleus.store.rdbms.table.AbstractTable.executeDdlStatement(AbstractTable.java:879) > > >>>> > at > > >>>> > > > >>>> > > > >>>> > > > org.datanucleus.store.rdbms.table.TableImpl.createForeignKeys(TableImpl.java:522) > > >>>> > at > > >>>> > > > >>>> > > > >>>> > > > org.datanucleus.store.rdbms.table.TableImpl.createConstraints(TableImpl.java:426) > > >>>> > at > > >>>> > > > >>>> > > > >>>> > > > org.datanucleus.store.rdbms.RDBMSStoreManager$ClassAdder.performTablesValidation(RDBMSStoreManager.java:3443) > > >>>> > at > > >>>> > > > >>>> > > > >>>> > > > org.datanucleus.store.rdbms.RDBMSStoreManager$ClassAdder.run(RDBMSStoreManager.java:2880) > > >>>> > at > > >>>> > > > >>>> > > > >>>> > > > org.datanucleus.store.rdbms.AbstractSchemaTransaction.execute(AbstractSchemaTransaction.java:119) > > >>>> > at > > >>>> > > > >>>> > > > >>>> > > > org.datanucleus.store.rdbms.RDBMSStoreManager.manageClasses(RDBMSStoreManager.java:1612) > > >>>> > at > > >>>> > > > >>>> > > > >>>> > > > org.datanucleus.store.rdbms.RDBMSStoreManager.getDatastoreClass(RDBMSStoreManager.java:675) > > >>>> > at > > >>>> > > > >>>> > > > >>>> > > > org.datanucleus.store.rdbms.RDBMSPersistenceHandler.getDatastoreClass(RDBMSPersistenceHandler.java:88) > > >>>> > at > > >>>> > > > >>>> > > > >>>> > > > org.datanucleus.store.rdbms.RDBMSPersistenceHandler.insertObject(RDBMSPersistenceHandler.java:123) > > >>>> > at > > >>>> > > > >>>> > > > >>>> > > > org.datanucleus.state.StateManagerImpl.internalMakePersistent(StateManagerImpl.java:3363) > > >>>> > at > > >>>> > > > >>>> > > > >>>> > > > org.datanucleus.state.StateManagerImpl.makePersistent(StateManagerImpl.java:3339) > > >>>> > at > > >>>> > > > >>>> > > > >>>> > > > org.datanucleus.ExecutionContextImpl.persistObjectInternal(ExecutionContextImpl.java:2066) > > >>>> > at > > >>>> > > > >>>> > > > >>>> > > > org.datanucleus.ExecutionContextImpl.persistObjectWork(ExecutionContextImpl.java:1909) > > >>>> > at > > >>>> > > > >>>> > > > >>>> > > > org.datanucleus.ExecutionContextImpl.persistObject(ExecutionContextImpl.java:1764) > > >>>> > at > > >>>> > > > >>>> > > > >>>> > > > org.datanucleus.api.jdo.JDOPersistenceManager.jdoMakePersistent(JDOPersistenceManager.java:720) > > >>>> > at > > >>>> > > > >>>> > > > >>>> > > > org.datanucleus.api.jdo.JDOPersistenceManager.makePersistent(JDOPersistenceManager.java:745) > > >>>> > at > > >>>> > > > >>>> > > > >>>> > > > org.apache.isis.objectstore.jdo.datanucleus.persistence.commands.DataNucleusCreateObjectCommand.execute(DataNucleusCreateObjectCommand.java:54) > > >>>> > at > > >>>> > > > >>>> > > > >>>> > > > org.apache.isis.objectstore.jdo.datanucleus.DataNucleusObjectStore.executeCommands(DataNucleusObjectStore.java:365) > > >>>> > at > > >>>> > > > >>>> > > > >>>> > > > org.apache.isis.objectstore.jdo.datanucleus.DataNucleusObjectStore.execute(DataNucleusObjectStore.java:359) > > >>>> > at > > >>>> > > > >>>> > > > >>>> > > > org.apache.isis.core.runtime.system.transaction.IsisTransaction.doFlush(IsisTransaction.java:527) > > >>>> > at > > >>>> > > > >>>> > > > >>>> > > > org.apache.isis.core.runtime.system.transaction.IsisTransaction.flush(IsisTransaction.java:473) > > >>>> > at > > >>>> > > > >>>> > > > >>>> > > > org.apache.isis.core.runtime.system.transaction.IsisTransactionManager.flushTransaction(IsisTransactionManager.java:392) > > >>>> > at > > >>>> > > > >>>> > > > >>>> > > > org.apache.isis.viewer.wicket.ui.components.actions.ActionPanel.executeActionOnTargetAndProcessResults(ActionPanel.java:249) > > >>>> > at > > >>>> > > > >>>> > > > >>>> > > > org.apache.isis.viewer.wicket.ui.components.actions.ActionPanel.executeActionAndProcessResults(ActionPanel.java:193) > > >>>> > at > > >>>> > > > >>>> > > > >>>> > > > org.apache.isis.viewer.wicket.ui.components.actions.ActionParametersFormPanel$ActionParameterForm$1.onSubmit(ActionParametersFormPanel.java:145) > > >>>> > at > > >>>> > > > >>>> > > > >>>> > > > org.apache.wicket.ajax.markup.html.form.AjaxButton$1.onSubmit(AjaxButton.java:108) > > >>>> > at > > >>>> > > > >>>> > > > >>>> > > > org.apache.wicket.ajax.form.AjaxFormSubmitBehavior$1.onSubmit(AjaxFormSubmitBehavior.java:182) > > >>>> > at > > >>>> > > > org.apache.wicket.markup.html.form.Form.delegateSubmit(Form.java:1266) > > >>>> > at > > org.apache.wicket.markup.html.form.Form.process(Form.java:938) > > >>>> > at > > >>>> > > > org.apache.wicket.markup.html.form.Form.onFormSubmitted(Form.java:770) > > >>>> > at > > >>>> > > > >>>> > > > >>>> > > > org.apache.wicket.ajax.form.AjaxFormSubmitBehavior.onEvent(AjaxFormSubmitBehavior.java:159) > > >>>> > at > > >>>> > > > >>>> > > > >>>> > > > org.apache.wicket.ajax.AjaxEventBehavior.respond(AjaxEventBehavior.java:124) > > >>>> > at > > >>>> > > > >>>> > > > >>>> > > > org.apache.wicket.ajax.AbstractDefaultAjaxBehavior.onRequest(AbstractDefaultAjaxBehavior.java:633) > > >>>> > at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) > > >>>> > at > > >>>> > > > >>>> > > > >>>> > > > sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) > > >>>> > at > > >>>> > > > >>>> > > > >>>> > > > sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) > > >>>> > at java.lang.reflect.Method.invoke(Method.java:497) > > >>>> > at > > >>>> > > > >>>> > > > >>>> > > > org.apache.wicket.RequestListenerInterface.internalInvoke(RequestListenerInterface.java:258) > > >>>> > at > > >>>> > > > >>>> > > > >>>> > > > org.apache.wicket.RequestListenerInterface.invoke(RequestListenerInterface.java:241) > > >>>> > at > > >>>> > > > >>>> > > > >>>> > > > org.apache.wicket.core.request.handler.ListenerInterfaceRequestHandler.invokeListener(ListenerInterfaceRequestHandler.java:250) > > >>>> > at > > >>>> > > > >>>> > > > >>>> > > > org.apache.wicket.core.request.handler.ListenerInterfaceRequestHandler.respond(ListenerInterfaceRequestHandler.java:236) > > >>>> > at > > >>>> > > > >>>> > > > >>>> > > > org.apache.wicket.request.cycle.RequestCycle$HandlerExecutor.respond(RequestCycle.java:862) > > >>>> > at > > >>>> > > > >>>> > > > >>>> > > > org.apache.wicket.request.RequestHandlerStack.execute(RequestHandlerStack.java:64) > > >>>> > at > > >>>> > > > >>>> > > > org.apache.wicket.request.cycle.RequestCycle.execute(RequestCycle.java:261) > > >>>> > at > > >>>> > > > >>>> > > > >>>> > > > org.apache.wicket.request.cycle.RequestCycle.processRequest(RequestCycle.java:218) > > >>>> > at > > >>>> > > > >>>> > > > >>>> > > > org.apache.wicket.request.cycle.RequestCycle.processRequestAndDetach(RequestCycle.java:289) > > >>>> > at > > >>>> > > > >>>> > > > >>>> > > > org.apache.wicket.protocol.http.WicketFilter.processRequestCycle(WicketFilter.java:259) > > >>>> > at > > >>>> > > > >>>> > > > >>>> > > > org.apache.wicket.protocol.http.WicketFilter.processRequest(WicketFilter.java:201) > > >>>> > at > > >>>> > > > >>>> > > > >>>> > > > org.apache.wicket.protocol.http.WicketFilter.doFilter(WicketFilter.java:282) > > >>>> > at > > >>>> > > > >>>> > > > >>>> > > > org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1212) > > >>>> > at > > >>>> > > > >>>> > > > >>>> > > > org.apache.isis.core.webapp.diagnostics.IsisLogOnExceptionFilter.doFilter(IsisLogOnExceptionFilter.java:52) > > >>>> > at > > >>>> > > > >>>> > > > >>>> > > > org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1212) > > >>>> > at > > >>>> > > > >>>> > > > >>>> > > > org.apache.shiro.web.servlet.AbstractShiroFilter.executeChain(AbstractShiroFilter.java:449) > > >>>> > at > > >>>> > > > >>>> > > > >>>> > > > org.apache.shiro.web.servlet.AbstractShiroFilter$1.call(AbstractShiroFilter.java:365) > > >>>> > at > > >>>> > > > >>>> > > > >>>> > > > org.apache.shiro.subject.support.SubjectCallable.doCall(SubjectCallable.java:90) > > >>>> > at > > >>>> > > > >>>> > > > >>>> > > > org.apache.shiro.subject.support.SubjectCallable.call(SubjectCallable.java:83) > > >>>> > at > > >>>> > > > >>>> > > > >>>> > > > org.apache.shiro.subject.support.DelegatingSubject.execute(DelegatingSubject.java:383) > > >>>> > at > > >>>> > > > >>>> > > > >>>> > > > org.apache.shiro.web.servlet.AbstractShiroFilter.doFilterInternal(AbstractShiroFilter.java:362) > > >>>> > at > > >>>> > > > >>>> > > > >>>> > > > org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:125) > > >>>> > at > > >>>> > > > >>>> > > > >>>> > > > org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1212) > > >>>> > at > > >>>> > > > >>>> > > org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:399) > > >>>> > at > > >>>> > > > >>>> > > > org.mortbay.jetty.security.SecurityHandler.handle(SecurityHandler.java:216) > > >>>> > at > > >>>> > > > >>>> > > org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:182) > > >>>> > at > > >>>> > > > >>>> > > org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:766) > > >>>> > at > > >>>> > > > org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:450) > > >>>> > at > > >>>> > > > >>>> > > > >>>> > > > org.mortbay.jetty.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:230) > > >>>> > at > > >>>> > > > >>>> > > > >>>> > > > org.mortbay.jetty.handler.HandlerCollection.handle(HandlerCollection.java:114) > > >>>> > at > > >>>> > > > >>>> > > org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152) > > >>>> > at org.mortbay.jetty.Server.handle(Server.java:326) > > >>>> > at > > >>>> > > > >>>> > > org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:542) > > >>>> > at > > >>>> > > > >>>> > > > >>>> > > > org.mortbay.jetty.HttpConnection$RequestHandler.content(HttpConnection.java:945) > > >>>> > at org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:756) > > >>>> > at > > >>>> org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:218) > > >>>> > at > > >>>> org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:404) > > >>>> > at > > >>>> > > > >>>> > > > >>>> > > > org.mortbay.io.nio.SelectChannelEndPoint.run(SelectChannelEndPoint.java:410) > > >>>> > at > > >>>> > > > >>>> > > > >>>> > > > org.mortbay.thread.QueuedThreadPool$PoolThread.run(QueuedThreadPool.java:582) > > >>>> > Caused by: org.hsqldb.HsqlException: a FOREIGN KEY constraint > > already > > >>>> > exists on the set of columns: "activity_FK7" > > >>>> > at org.hsqldb.error.Error.error(Unknown Source) > > >>>> > at org.hsqldb.error.Error.error(Unknown Source) > > >>>> > at org.hsqldb.TableWorks.checkCreateForeignKey(Unknown Source) > > >>>> > at org.hsqldb.TableWorks.addForeignKey(Unknown Source) > > >>>> > at org.hsqldb.StatementSchema.getResult(Unknown Source) > > >>>> > at org.hsqldb.StatementSchema.execute(Unknown Source) > > >>>> > at org.hsqldb.Session.executeCompiledStatement(Unknown Source) > > >>>> > at org.hsqldb.Session.executeDirectStatement(Unknown Source) > > >>>> > at org.hsqldb.Session.execute(Unknown Source) > > >>>> > ... 81 more > > >>>> > > > >>>> > > > >>>> > On Wed, Sep 2, 2015 at 9:24 AM, Stephen Cameron < > > >>>> > [email protected]> > > >>>> > wrote: > > >>>> > > > >>>> > > > > >>>> > > Hi > > >>>> > > > > >>>> > > Your solution ends up doing what mine does at the database > schema > > >>>> level. > > >>>> > > > > >>>> > > If Datanucleus supports it then shouldn't it be mostly be fine > in > > >>>> Isis? > > >>>> > If > > >>>> > > not then Isis should warn. > > >>>> > > > > >>>> > > I appreciate your help. > > >>>> > > > > >>>> > > > > >>>> > > > > >>>> > > > > >>>> > > On Wed, Sep 2, 2015 at 4:58 AM, Jeroen van der Wal < > > >>>> [email protected]> > > >>>> > > wrote: > > >>>> > > > > >>>> > >> I've never used @PrimaryKey in an Isis application, don't know > if > > >>>> that > > >>>> > >> works. My abstract class would typically look like this: > > >>>> > >> > > >>>> > >> @PersistenceCapable(identityType = IdentityType.DATASTORE) > > >>>> > >> @DatastoreIdentity(column = "id", strategy = > > >>>> > IdGeneratorStrategy.IDENTITY) > > >>>> > >> @Inheritance(strategy = InheritanceStrategy.SUBCLASS_TABLE) > > >>>> > >> public abstract class AbstractParentType { > > >>>> > >> > > >>>> > >> private String name; > > >>>> > >> > > >>>> > >> @Column(allowsNull="true") > > >>>> > >> @MemberOrder(sequence = "1") > > >>>> > >> public String getName() { > > >>>> > >> return name; > > >>>> > >> } > > >>>> > >> > > >>>> > >> public void setName(final String name) { > > >>>> > >> this.name = name; > > >>>> > >> } > > >>>> > >> > > >>>> > >> } > > >>>> > >> > > >>>> > >> Hth > > >>>> > >> > > >>>> > >> On 1 September 2015 at 20:44, Jeroen van der Wal < > > >>>> [email protected]> > > >>>> > >> wrote: > > >>>> > >> > > >>>> > >> > If you make your abstract class public it should work fine > ;-) > > >>>> > >> > > > >>>> > >> > Cheers, > > >>>> > >> > > > >>>> > >> > Jeroen > > >>>> > >> > > > >>>> > >> > On 1 September 2015 at 15:12, Stephen Cameron < > > >>>> > >> [email protected]> > > >>>> > >> > wrote: > > >>>> > >> > > > >>>> > >> >> Here a two scenarios each with a Parent and Child Type, they > > >>>> should > > >>>> > >> give > > >>>> > >> >> the same result > > >>>> > >> >> > > >>>> > >> >> 1. Concrete Parent Type > > >>>> > >> >> > > >>>> > >> >> @PersistenceCapable() > > >>>> > >> >> public class ConcreteParentType { > > >>>> > >> >> > > >>>> > >> >> @PrimaryKey() > > >>>> > >> >> @Persistent(valueStrategy=IdGeneratorStrategy.INCREMENT) > > >>>> > >> >> private Long id; > > >>>> > >> >> > > >>>> > >> >> private String name; > > >>>> > >> >> > > >>>> > >> >> @Column(allowsNull="true") > > >>>> > >> >> @MemberOrder(sequence = "1") > > >>>> > >> >> public String getName() { > > >>>> > >> >> return name; > > >>>> > >> >> } > > >>>> > >> >> > > >>>> > >> >> public void setName(final String name) { > > >>>> > >> >> this.name = name; > > >>>> > >> >> } > > >>>> > >> >> > > >>>> > >> >> } > > >>>> > >> >> > > >>>> > >> >> @PersistenceCapable() > > >>>> > >> >> public class ChildTypeOfConcreteParentType extends > > >>>> > ConcreteParentType { > > >>>> > >> >> > > >>>> > >> >> > > >>>> > >> >> private String description; > > >>>> > >> >> > > >>>> > >> >> @Column(allowsNull="true") > > >>>> > >> >> @MemberOrder(sequence = "2") > > >>>> > >> >> public String getDescription() { > > >>>> > >> >> return description; > > >>>> > >> >> } > > >>>> > >> >> > > >>>> > >> >> public void setDescription(final String description) { > > >>>> > >> >> this.description = description; > > >>>> > >> >> } > > >>>> > >> >> > > >>>> > >> >> } > > >>>> > >> >> > > >>>> > >> >> 2. Abstract Parent Type > > >>>> > >> >> > > >>>> > >> >> @PersistenceCapable() > > >>>> > >> >> @Inheritance(strategy = InheritanceStrategy.SUBCLASS_TABLE) > > >>>> > >> >> abstract class AbstractParentType { > > >>>> > >> >> > > >>>> > >> >> @PrimaryKey() > > >>>> > >> >> @Persistent(valueStrategy=IdGeneratorStrategy.INCREMENT) > > >>>> > >> >> private Long id; > > >>>> > >> >> > > >>>> > >> >> private String name; > > >>>> > >> >> > > >>>> > >> >> @Column(allowsNull="true") > > >>>> > >> >> @MemberOrder(sequence = "1") > > >>>> > >> >> public String getName() { > > >>>> > >> >> return name; > > >>>> > >> >> } > > >>>> > >> >> > > >>>> > >> >> public void setName(final String name) { > > >>>> > >> >> this.name = name; > > >>>> > >> >> } > > >>>> > >> >> > > >>>> > >> >> } > > >>>> > >> >> > > >>>> > >> >> @PersistenceCapable() > > >>>> > >> >> public class ChildTypeOfAbstractParentType extends > > >>>> > AbstractParentType { > > >>>> > >> >> > > >>>> > >> >> private String description; > > >>>> > >> >> > > >>>> > >> >> @Column(allowsNull="true") > > >>>> > >> >> @MemberOrder(sequence = "2") > > >>>> > >> >> public String getDescription() { > > >>>> > >> >> return description; > > >>>> > >> >> } > > >>>> > >> >> > > >>>> > >> >> public void setDescription(final String description) { > > >>>> > >> >> this.description = description; > > >>>> > >> >> } > > >>>> > >> >> > > >>>> > >> >> } > > >>>> > >> >> > > >>>> > >> >> In the seond scenario the name property doesn't appear, only > > the > > >>>> > >> >> description. > > >>>> > >> >> > > >>>> > >> >> The DomainService class for testing these two scenarios in > the > > >>>> viewer > > >>>> > >> is > > >>>> > >> >> this: > > >>>> > >> >> > > >>>> > >> >> @DomainService(nature=NatureOfService.VIEW_MENU_ONLY) > > >>>> > >> >> @DomainServiceLayout(named = "DataNucleus", menuBar = > > >>>> > MenuBar.PRIMARY, > > >>>> > >> >> menuOrder = "100") > > >>>> > >> >> public class Menu { > > >>>> > >> >> > > >>>> > >> >> > > >>>> > >> >> > > >>>> > >> >> public ChildTypeOfConcreteParentType > > >>>> > >> >> createChildTypeOfConcreteParentType() { > > >>>> > >> >> ChildTypeOfConcreteParentType childType = null; > > >>>> > >> >> try { > > >>>> > >> >> childType = > > >>>> > >> >> > > >>>> container.newTransientInstance(ChildTypeOfConcreteParentType.class); > > >>>> > >> >> > > childType.setName("ChildTypeOfConcreteParentType"); > > >>>> > >> >> childType.setDescription("something > descriptive"); > > >>>> > >> >> container.persistIfNotAlready(childType); > > >>>> > >> >> } catch (Exception e) { > > >>>> > >> >> e.printStackTrace(); > > >>>> > >> >> } > > >>>> > >> >> return childType; > > >>>> > >> >> } > > >>>> > >> >> > > >>>> > >> >> public ChildTypeOfAbstractParentType > > >>>> > >> >> createChildTypeOfAbstractParentType() { > > >>>> > >> >> ChildTypeOfAbstractParentType childType = null; > > >>>> > >> >> try { > > >>>> > >> >> childType = > > >>>> > >> >> > > >>>> container.newTransientInstance(ChildTypeOfAbstractParentType.class); > > >>>> > >> >> > > childType.setName("ChildTypeOfAbstractParentType"); > > >>>> > >> >> childType.setDescription("something > descriptive"); > > >>>> > >> >> container.persistIfNotAlready(childType); > > >>>> > >> >> } catch (Exception e) { > > >>>> > >> >> e.printStackTrace(); > > >>>> > >> >> } > > >>>> > >> >> return childType; > > >>>> > >> >> } > > >>>> > >> >> > > >>>> > >> >> > > >>>> > >> >> > > >>>> > >> >> @javax.inject.Inject > > >>>> > >> >> DomainObjectContainer container; > > >>>> > >> >> > > >>>> > >> >> } > > >>>> > >> >> > > >>>> > >> >> > > >>>> > >> >> On Tue, Sep 1, 2015 at 10:42 PM, Stephen Cameron < > > >>>> > >> >> [email protected] > > >>>> > >> >> > wrote: > > >>>> > >> >> > > >>>> > >> >> > Hi Jeroen, just noticed this after sending second update > > >>>> (winge). > > >>>> > >> >> > > > >>>> > >> >> > I'll send a test case now. > > >>>> > >> >> > > > >>>> > >> >> > On Tue, Sep 1, 2015 at 10:29 PM, Jeroen van der Wal < > > >>>> > >> >> [email protected]> > > >>>> > >> >> > wrote: > > >>>> > >> >> > > > >>>> > >> >> >> Hi Stephen, > > >>>> > >> >> >> > > >>>> > >> >> >> Can you share some code to support your case? > > >>>> > >> >> >> > > >>>> > >> >> >> Cheers, > > >>>> > >> >> >> > > >>>> > >> >> >> Jeroen > > >>>> > >> >> >> > > >>>> > >> >> >> On 1 September 2015 at 12:39, Stephen Cameron < > > >>>> > >> >> [email protected] > > >>>> > >> >> >> > > > >>>> > >> >> >> wrote: > > >>>> > >> >> >> > > >>>> > >> >> >> > Hi, > > >>>> > >> >> >> > > > >>>> > >> >> >> > I've been trying today to find solutions to what seem > to > > be > > >>>> > >> >> Datanucleus > > >>>> > >> >> >> > issues, but without much success. So rather than solve > > the > > >>>> > >> problems > > >>>> > >> >> >> created > > >>>> > >> >> >> > in my refactoring of my application, which has been too > > >>>> hard > > >>>> > >> frankly, > > >>>> > >> >> >> I'm > > >>>> > >> >> >> > trying to start afresh with some simple test cases, > show > > >>>> these > > >>>> > >> work, > > >>>> > >> >> >> then > > >>>> > >> >> >> > add more complexity till I get where I want to be. > > >>>> > >> >> >> > > > >>>> > >> >> >> > So, I am starting this approach and I immediately have > an > > >>>> issue, > > >>>> > >> but > > >>>> > >> >> >> not a > > >>>> > >> >> >> > Datanucleus one, I find that the value properties of an > > >>>> abstract > > >>>> > >> >> parent > > >>>> > >> >> >> > class don't appear in the Wicket viewer, whereas they > do > > >>>> if the > > >>>> > >> >> parent > > >>>> > >> >> >> > class is concrete. Is this correct and if so what is > the > > >>>> reason? > > >>>> > >> >> >> > > > >>>> > >> >> >> > Thanks. > > >>>> > >> >> >> > > > >>>> > >> >> >> > > >>>> > >> >> > > > >>>> > >> >> > > > >>>> > >> >> > > >>>> > >> > > > >>>> > >> > > > >>>> > >> > > >>>> > > > > >>>> > > > > >>>> > > > >>>> > > >>> > > >>> > > >> > > > > > >
