> 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
