Hi Andrus, I asked ChatGPT and it suggested adding the following two lines in addition to creating the EntityResolver as you suggested.
var namespace = new EntityResolver(List.of(mainMap, errorsMap)); mainMap.setNamespace(namespace); errorsMap.setNamespace(namespace); Now it is generating the target attribute for the relationships in the XML. Thank you Ricardo Parada > On Oct 14, 2025, at 5:54 PM, Andrus Adamchik <[email protected]> wrote: > > See my follow up email :) > >> On Oct 14, 2025, at 5:51 PM, Ricardo Parada <[email protected]> wrote: >> >> Andrus, >> >> What should I do then with the entity resolver? >> >> I created it like you said but it’s still not being used. >> >> Thank you >> Ricardo Parada >> >> >> >> >>>> On Oct 14, 2025, at 5:33 PM, Andrus Adamchik <[email protected]> wrote: >>> >>> >>>> >>>> I then save the first data map and it throws a NullPointerException. >>> >>> Before save, try this to make sure entities can find each other across >>> DataMaps: >>> >>> EntityResolver namespace = new EntityResolver(List.of(mainMap, errorsMap)); >>> >>>> (I avoided creating data nodes and the project in this code to keep things >>>> simple and illustrate the NullPointerException) >>> >>> BTW, if you have a single DataNode, don't bother creating it in the model. >>> It is much simpler and cleaner to just assign a DataSource when creating a >>> CayenneRuntime, and Cayenne will use it to handle all DataMaps in the >>> project. >>> >>> Andrus >>> >>> >>>> On Oct 14, 2025, at 5:23 PM, Ricardo Parada <[email protected]> >>>> wrote: >>>> >>>> Here is a very minimal test of what I am seeing. >>>> >>>> Two data maps: Main and Errors. >>>> >>>> I have an APP_USER DbTable in the Main data map and an APP_ERROR DbTable >>>> in the Errors data map. >>>> >>>> Then I have a to-many relationship and inverse to one between these two. >>>> >>>> APP_USER <->> APP_ERROR >>>> >>>> I then simply create the ObjEntity, ObjAttribute and ObjRelationship >>>> objects programmatically. >>>> >>>> I then save the first data map and it throws a NullPointerException. >>>> >>>> Here is the isolated test: >>>> >>>> (I avoided creating data nodes and the project in this code to keep things >>>> simple and illustrate the NullPointerException) >>>> >>>> package play.cay.utils.conversion; >>>> >>>> import java.io.PrintWriter; >>>> import java.sql.Types; >>>> >>>> import org.apache.cayenne.configuration.EmptyConfigurationNodeVisitor; >>>> import org.apache.cayenne.map.DataMap; >>>> import org.apache.cayenne.map.DbAttribute; >>>> import org.apache.cayenne.map.DbEntity; >>>> import org.apache.cayenne.map.DbJoin; >>>> import org.apache.cayenne.map.DbRelationship; >>>> import org.apache.cayenne.map.ObjAttribute; >>>> import org.apache.cayenne.map.ObjEntity; >>>> import org.apache.cayenne.map.ObjRelationship; >>>> import org.apache.cayenne.util.XMLEncoder; >>>> >>>> public class DataMapTest { >>>> >>>> public static void main(String[] args) { >>>> // Create DataMaps >>>> DataMap mainMap = new DataMap("Main"); >>>> DataMap errorsMap = new DataMap("Errors"); >>>> >>>> // -------------------- DB Entities -------------------- >>>> >>>> // APP_USER DbEntity >>>> DbEntity appUserDb = new DbEntity("APP_USER"); >>>> DbAttribute appUserIdDbAttr = new DbAttribute("ID", Types.INTEGER, >>>> appUserDb); >>>> appUserIdDbAttr.setPrimaryKey(true); >>>> appUserDb.addAttribute(appUserIdDbAttr); >>>> appUserDb.addAttribute(new DbAttribute("NAME", Types.VARCHAR, >>>> appUserDb)); >>>> appUserDb.addAttribute(new DbAttribute("EMAIL", Types.VARCHAR, >>>> appUserDb)); >>>> appUserDb.getPrimaryKeyGenerator(); >>>> >>>> // APP_ERROR DbEntity >>>> DbEntity appErrorDb = new DbEntity("APP_ERROR"); >>>> DbAttribute appErrorIdDbAttr = new DbAttribute("ID", Types.INTEGER, >>>> appErrorDb); >>>> appErrorDb.addAttribute(appErrorIdDbAttr); >>>> appErrorDb.addAttribute(new DbAttribute("APP_USER_ID", Types.INTEGER, >>>> appErrorDb)); >>>> appErrorDb.addAttribute(new DbAttribute("ERROR_MESSAGE", >>>> Types.VARCHAR, appErrorDb)); >>>> >>>> // Add DbEntities to respective maps >>>> mainMap.addDbEntity(appUserDb); >>>> errorsMap.addDbEntity(appErrorDb); >>>> >>>> // -------------------- DB Relationships -------------------- >>>> >>>> // APP_ERROR -> APP_USER (to-one) >>>> DbRelationship toUserRel = new DbRelationship("appUser"); >>>> toUserRel.setSourceEntity(appErrorDb); >>>> toUserRel.setTargetEntityName(appUserDb); >>>> toUserRel.setToMany(false); >>>> toUserRel.addJoin(new DbJoin(toUserRel, "APP_USER_ID", "ID")); >>>> appErrorDb.addRelationship(toUserRel); >>>> >>>> // APP_USER ->> APP_ERROR (to-many) >>>> DbRelationship errorsRel = new DbRelationship("errors"); >>>> errorsRel.setSourceEntity(appUserDb); >>>> errorsRel.setTargetEntityName(appErrorDb); >>>> errorsRel.setToMany(true); >>>> errorsRel.addJoin(new DbJoin(errorsRel, "ID", "APP_USER_ID")); >>>> appUserDb.addRelationship(errorsRel); >>>> >>>> // -------------------- ObjEntities -------------------- >>>> >>>> // APP_USER ObjEntity >>>> ObjEntity appUserObj = new ObjEntity("AppUser"); >>>> appUserObj.setDbEntity(appUserDb); >>>> appUserObj.addAttribute(new ObjAttribute("id", "java.lang.Integer", >>>> appUserObj)); >>>> appUserObj.addAttribute(new ObjAttribute("name", "java.lang.String", >>>> appUserObj)); >>>> appUserObj.addAttribute(new ObjAttribute("email", "java.lang.String", >>>> appUserObj)); >>>> >>>> // APP_ERROR ObjEntity >>>> ObjEntity appErrorObj = new ObjEntity("AppError"); >>>> appErrorObj.setDbEntity(appErrorDb); >>>> appErrorObj.addAttribute(new ObjAttribute("id", "java.lang.Integer", >>>> appErrorObj)); >>>> appErrorObj.addAttribute(new ObjAttribute("errorMessage", >>>> "java.lang.String", appErrorObj)); >>>> >>>> // Add ObjEntities to respective maps >>>> mainMap.addObjEntity(appUserObj); >>>> errorsMap.addObjEntity(appErrorObj); >>>> >>>> // -------------------- ObjRelationships -------------------- >>>> >>>> // AppError â AppUser (to-one) >>>> ObjRelationship appUserRel = new ObjRelationship("appUser"); >>>> appUserRel.setSourceEntity(appErrorObj); >>>> appUserRel.setTargetEntityName(appUserObj); // sets target name >>>> appUserRel.setDbRelationshipPath("appUser"); >>>> appErrorObj.addRelationship(appUserRel); >>>> >>>> // AppUser â AppError (to-many) >>>> ObjRelationship errorsRelObj = new ObjRelationship("errors"); >>>> errorsRelObj.setSourceEntity(appUserObj); >>>> errorsRelObj.setTargetEntityName(appErrorObj); // sets target name >>>> errorsRelObj.setDbRelationshipPath("errors"); >>>> appUserObj.addRelationship(errorsRelObj); >>>> >>>> PrintWriter stdout = new PrintWriter(System.out, true); >>>> XMLEncoder encoder = new XMLEncoder(stdout, "\t", "11"); >>>> EmptyConfigurationNodeVisitor visitor = new >>>> EmptyConfigurationNodeVisitor(); >>>> >>>> stdout.println(mainMap.getName()); >>>> stdout.println(); >>>> encoder.nested(mainMap, visitor); >>>> >>>> stdout.println(); >>>> stdout.println(); >>>> >>>> stdout.println(errorsMap.getName()); >>>> stdout.println(); >>>> encoder.nested(errorsMap, visitor); >>>> >>>> } >>>> } >>>> >>>> >>>> >>>>> >>>>>> On Oct 14, 2025, at 3:29 PM, Ricardo Parada <[email protected]> wrote: >>>>> >>>>> Hello, >>>>> >>>>> I wrote a converter to convert our eomodels from EOF to >>>>> Cayenne-project.xml and data maps .map.xml >>>>> >>>>> So far so good. However, I seem to be running into a problem for cross >>>>> data map relationships. >>>>> >>>>> I’m using 5.0-M1. >>>>> >>>>> When I’m creating the ObjRelationship I call: >>>>> >>>>> objRel.setTargetEntityName(targetObjEntity); >>>>> >>>>> If I then call objRel.getTargetEntityName() it returns the correct target >>>>> entity name. >>>>> >>>>> However, if I call objRel.getTargetEntity() it returns null. >>>>> >>>>> I debugged the code and I can see that getTargetEntity() is looking for >>>>> the target entity name in the data map corresponding to the source >>>>> ObjEntity. And it does not find it and returns null for that reason. >>>>> >>>>> As a result of that, when I call encodeAsXML() on objRel I see that the >>>>> XML is missing the target attribute in the obj-relationship xml tag. >>>>> >>>>> Is this a bug in 5.0-M1 or am I missing something when creating my >>>>> ObjRelationship programmatically. >>>>> >>>>> I could put all eomodels that have cross eomodel relationships into the >>>>> same data map to avoid this problem. >>>>> >>>>> But when I create it in Cayenne Modeler 4.3.3 it seems to work. I see the >>>>> obj-relationship in the XML have target correctly set. >>>>> >>>>> Thank you all in advance. >>>>> Ricardo Parada >>> >
