> 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

Reply via email to