# Error when saving Bounds2DComponent (serialization error)

**URL:** <https://forum.inductiveautomation.com/t/error-when-saving-bounds2dcomponent-serialization-error/96276>\
**Category:** Module Development\
**Tags:** vision\
**Created:** [September 21, 2024, 11:10am UTC](https://forum.inductiveautomation.com/t/error-when-saving-bounds2dcomponent-serialization-error/96276 "2024-09-21T11:10:11Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![Bohdan](https://avatars.discourse-cdn.com/v4/letter/b/bbce88/32.png) [@Bohdan](https://forum.inductiveautomation.com/u/Bohdan)\
**Post date:** [September 21, 2024, 11:10am UTC](https://forum.inductiveautomation.com/t/error-when-saving-bounds2dcomponent-serialization-error/96276/1 "2024-09-21T11:10:11Z")

</div>

Hi Guys,

I have implemented `Bounds2DComponent` interface for my vision component (extending `AbstractVisionComponent`) and it seems to work/behave well until I trying to save project with it in Designer.

I believe I am missing some property that perhaps should be specified in according `BeanInfo` class. I did tried to add `boundingRect` as well as `originalBounds` properties there but I still getting serialization error.

The only hint I have is what says in javadoc of `FPMILayout`:

> public static java.awt.geom.Rectangle2D getPreferredBounds​(javax.swing.JComponent comp)
> 
> Provides a consistent way to get the preferred bounds of a component. This is the bounding box of a component as it was last time it's parent container's layout was validated in the designer. Layouts may use this box to derive a new bounding box if the parent container changes. This function detects for the two ways that this box is stored:
> 
> ```
> Normal JComponent: Uses Jcomponent's preferred size property as the Dimension, and the FPMI_LC's preferred location Point to create the rectangle.
> Bounds2DComponent: Uses the originalBounds property.
> 
> ```

But I still unable to get it working. Besides implementing methods of `Bounds2DComponent` in my class, what else do I need to supplement and how? Please see error below (I did made sure that non of `getBoundingRect()` or `getOriginalBounds()` methods will ever return `null`, but I still getting:

```python
Caused by: java.lang.IllegalArgumentException: null
	at com.inductiveautomation.factorypmi.application.components.util.FPMILayout._getPrefSize(FPMILayout.java:159)
	at com.inductiveautomation.factorypmi.designer.xmlserialization.DefaultComponentDelegate.serializeComponentCommons(DefaultComponentDelegate.java:76)

```

Any hints what methods or properties does it try to read that returns `null`:

```python
com.inductiveautomation.ignition.client.util.gui.ErrorUtil - Error Saving the container
com.inductiveautomation.ignition.common.xmlserialization.SerializationException: Error during serialization for property 'contentPane' on object '[FPMIWindow]TestMainWindow'
	at com.inductiveautomation.ignition.common.xmlserialization.serialization.DefaultObjectSerializationDelegate.serializeProperties(DefaultObjectSerializationDelegate.java:307)
	at com.inductiveautomation.factorypmi.designer.xmlserialization.WindowDelegate.serialize(WindowDelegate.java:34)
	at com.inductiveautomation.ignition.common.xmlserialization.serialization.XMLSerializationContext.serialize(XMLSerializationContext.java:49)
	at com.inductiveautomation.ignition.common.xmlserialization.serialization.XMLSerializer.serialize(XMLSerializer.java:525)
	at com.inductiveautomation.ignition.common.xmlserialization.serialization.XMLSerializer.serializeBinary(XMLSerializer.java:507)
	at com.inductiveautomation.factorypmi.designer.workspace.WindowWorkspace.saveContainer(WindowWorkspace.java:1823)
	at com.inductiveautomation.factorypmi.designer.workspace.WindowWorkspace.commitDesignable(WindowWorkspace.java:1539)
	at com.inductiveautomation.factorypmi.designer.workspace.WindowWorkspace.commitAll(WindowWorkspace.java:1096)
	at com.inductiveautomation.factorypmi.designer.model.VisionDesignerImpl.notifyProjectSaveStart(VisionDesignerImpl.java:620)
	at com.inductiveautomation.ignition.designer.IgnitionDesigner.commitAll(IgnitionDesigner.java:1608)
	at com.inductiveautomation.ignition.designer.IgnitionDesigner.handleSave(IgnitionDesigner.java:1373)
	at com.inductiveautomation.ignition.designer.IgnitionDesigner$Handler.handleSaveAction(IgnitionDesigner.java:2820)
	at com.inductiveautomation.ignition.designer.IgnitionDesigner$Handler$5.actionPerformed(IgnitionDesigner.java:2400)
	at java.desktop/javax.swing.AbstractButton.fireActionPerformed(Unknown Source)
	at java.desktop/javax.swing.AbstractButton$Handler.actionPerformed(Unknown Source)
	at java.desktop/javax.swing.DefaultButtonModel.fireActionPerformed(Unknown Source)
	at java.desktop/javax.swing.DefaultButtonModel.setPressed(Unknown Source)
	at java.desktop/javax.swing.plaf.basic.BasicButtonListener.mouseReleased(Unknown Source)
	at com.jidesoft.plaf.basic.BasicJideButtonListener.mouseReleased(Unknown Source)
	at java.desktop/java.awt.AWTEventMulticaster.mouseReleased(Unknown Source)
	at java.desktop/java.awt.Component.processMouseEvent(Unknown Source)
	at java.desktop/javax.swing.JComponent.processMouseEvent(Unknown Source)
	at java.desktop/java.awt.Component.processEvent(Unknown Source)
	at java.desktop/java.awt.Container.processEvent(Unknown Source)
	at java.desktop/java.awt.Component.dispatchEventImpl(Unknown Source)
	at java.desktop/java.awt.Container.dispatchEventImpl(Unknown Source)
	at java.desktop/java.awt.Component.dispatchEvent(Unknown Source)
	at java.desktop/java.awt.LightweightDispatcher.retargetMouseEvent(Unknown Source)
	at java.desktop/java.awt.LightweightDispatcher.processMouseEvent(Unknown Source)
	at java.desktop/java.awt.LightweightDispatcher.dispatchEvent(Unknown Source)
	at java.desktop/java.awt.Container.dispatchEventImpl(Unknown Source)
	at java.desktop/java.awt.Window.dispatchEventImpl(Unknown Source)
	at java.desktop/java.awt.Component.dispatchEvent(Unknown Source)
	at java.desktop/java.awt.EventQueue.dispatchEventImpl(Unknown Source)
	at java.desktop/java.awt.EventQueue$4.run(Unknown Source)
	at java.desktop/java.awt.EventQueue$4.run(Unknown Source)
	at java.base/java.security.AccessController.doPrivileged(Native Method)
	at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(Unknown Source)
	at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(Unknown Source)
	at java.desktop/java.awt.EventQueue$5.run(Unknown Source)
	at java.desktop/java.awt.EventQueue$5.run(Unknown Source)
	at java.base/java.security.AccessController.doPrivileged(Native Method)
	at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(Unknown Source)
	at java.desktop/java.awt.EventQueue.dispatchEvent(Unknown Source)
	at java.desktop/java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
	at java.desktop/java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
	at java.desktop/java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
	at java.desktop/java.awt.EventDispatchThread.pumpEvents(Unknown Source)
	at java.desktop/java.awt.EventDispatchThread.pumpEvents(Unknown Source)
	at java.desktop/java.awt.EventDispatchThread.run(Unknown Source)
Caused by: java.lang.IllegalArgumentException: null
	at com.inductiveautomation.factorypmi.application.components.util.FPMILayout._getPrefSize(FPMILayout.java:159)
	at com.inductiveautomation.factorypmi.designer.xmlserialization.DefaultComponentDelegate.serializeComponentCommons(DefaultComponentDelegate.java:76)
	at com.inductiveautomation.factorypmi.designer.xmlserialization.DefaultComponentDelegate.serializeProperties(DefaultComponentDelegate.java:110)
	at com.inductiveautomation.ignition.common.xmlserialization.serialization.DefaultObjectSerializationDelegate.serialize(DefaultObjectSerializationDelegate.java:334)
	at com.inductiveautomation.ignition.common.xmlserialization.serialization.XMLSerializationContext.serialize(XMLSerializationContext.java:49)
	at com.inductiveautomation.ignition.common.xmlserialization.serialization.DefaultObjectSerializationDelegate.writeCall(DefaultObjectSerializationDelegate.java:240)
	at com.inductiveautomation.factorypmi.designer.xmlserialization.BasicContainerDelegate.serializeProperties(BasicContainerDelegate.java:120)
	at com.inductiveautomation.factorypmi.designer.xmlserialization.BasicContainerDelegate.serialize(BasicContainerDelegate.java:45)
	at com.inductiveautomation.ignition.common.xmlserialization.serialization.XMLSerializationContext.serialize(XMLSerializationContext.java:49)
	at com.inductiveautomation.ignition.common.xmlserialization.serialization.DefaultObjectSerializationDelegate.writeCall(DefaultObjectSerializationDelegate.java:240)
	at com.inductiveautomation.ignition.common.xmlserialization.serialization.DefaultObjectSerializationDelegate.writeCall(DefaultObjectSerializationDelegate.java:227)
	at com.inductiveautomation.ignition.common.xmlserialization.serialization.DefaultObjectSerializationDelegate.doProperty(DefaultObjectSerializationDelegate.java:284)
	at com.inductiveautomation.ignition.common.xmlserialization.serialization.DefaultObjectSerializationDelegate.serializeProperties(DefaultObjectSerializationDelegate.java:305)
	... 49 common frames omitted

```

Many thanks!

---

<div class="post-metadata">

**Author:** ![pturmel](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pturmel/32/3295_2.png) [@pturmel](https://forum.inductiveautomation.com/u/pturmel)\
**Post date:** [September 21, 2024, 4:45pm UTC](https://forum.inductiveautomation.com/t/error-when-saving-bounds2dcomponent-serialization-error/96276/2 "2024-09-21T16:45:30Z")

</div>

FPMILayout uses a Swing client property on the component to hold its UI information, including the preferred size. There probably something missing in your constructor chain that would set the UI layout.

Unrelated to BeanInfo.

---

<div class="post-metadata">

**Author:** ![Bohdan](https://avatars.discourse-cdn.com/v4/letter/b/bbce88/32.png) [@Bohdan](https://forum.inductiveautomation.com/u/Bohdan)\
**Post date:** [September 21, 2024, 7:37pm UTC](https://forum.inductiveautomation.com/t/error-when-saving-bounds2dcomponent-serialization-error/96276/3 "2024-09-21T19:37:59Z")

</div>

Hi Pturmel,

Thank you for your quick respond! How to understand javadoc info on FPMILayout then:

```python
Normal JComponent: Uses Jcomponent's preferred size property as the Dimension, and the FPMI_LC's preferred location Point to create the rectangle.
Bounds2DComponent: Uses the originalBounds property.

```

How/where do I need to add such `originalBounds` property since it is `Bounds2DComponent`, to comply with above?

Thank you!

---

<div class="post-metadata">

**Author:** ![pturmel](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pturmel/32/3295_2.png) [@pturmel](https://forum.inductiveautomation.com/u/pturmel)\
**Post date:** [September 21, 2024, 7:40pm UTC](https://forum.inductiveautomation.com/t/error-when-saving-bounds2dcomponent-serialization-error/96276/4 "2024-09-21T19:40:38Z")

</div>

No further clue.

---

<div class="post-metadata">

**Author:** ![Mathias\_Melling](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/mathias_melling/32/67682_2.png) [@Mathias\_Melling](https://forum.inductiveautomation.com/u/Mathias_Melling)\
**Post date:** [September 23, 2024, 2:09pm UTC](https://forum.inductiveautomation.com/t/error-when-saving-bounds2dcomponent-serialization-error/96276/5 "2024-09-23T14:09:29Z")

</div>

Hi Bohdan,

I've been building my components by extending the `AbstractVisionShape` class, which itself is an extension of `AbstractVisionComponent` and it also implements the `Bounds2DComponent` interface. Maybe that's the way to go for you as well, instead of trying to implement `Bounds2DComponent` yourself.

As to your question here:

> [@Vision Component Size restrictions](https://forum.inductiveautomation.com/t/vision-component-size-restrictions/83103/30):
>
> Hi Mathias, Could you please have a look at: [Error-When-Saving-Bounds2DComponent (Serialization error)](https://forum.inductiveautomation.com/t/error-when-saving-bounds2dcomponent-serialization-error/96276) It is related to what Max is trying to do too. I am asking you since you mentioned about need of boundingRect property... something I suspect I am doing wrong (any particular flags must be set for it to work, e.g. when using addProp(..) in the BeanInfo?). Any chance you can advice how exactly that property needs to be added and if you aware of anything else needed for such component to be sa…

I add the `boundingRect` property just like any other property:

```python
addProp("boundingRect",
		"Bounds",
		"Bounding rectangle of the component.",
		CAT_POSITION,
		HIDDEN_MASK);

```

I use the HIDDEN\_MASK, because there is no need for this property to be visible. It is only necessary for serialization.

---

<div class="post-metadata">

**Author:** ![Bohdan](https://avatars.discourse-cdn.com/v4/letter/b/bbce88/32.png) [@Bohdan](https://forum.inductiveautomation.com/u/Bohdan)\
**Post date:** [September 23, 2024, 4:06pm UTC](https://forum.inductiveautomation.com/t/error-when-saving-bounds2dcomponent-serialization-error/96276/6 "2024-09-23T16:06:13Z")

</div>

Hi Mathias,

Many thanks for your reply! I did followed your advice and slightly adapted my code to extend `AbstractVisionShape` instead. And it saves fine now with no errors! And indeed `boundingRect` property did the trick too (tried with and without it) to properly remember/save location of my component.

To Pturmel: Also would like to add (in case if anybody else will encounter such issue) that Pturmel was also correct that serialization exception that I had when saving my original `Bounds2DComponent` was apparently not related to missing property on `BeanInfo` (although needed to properly save/load location/size of the component), since even without it `AbstractVisionShape` version (unlike for the case of just implementing `Bounds2DComponent`) saves fine with no serialization errors (it just won't remember correct bounds if without `boundingRect` property).

So that is sorted!  
Thank you guys for your help!
