// 
//     Licensed to the Apache Software Foundation (ASF) under one
//     or more contributor license agreements.  See the NOTICE file
//     distributed with this work for additional information
//     regarding copyright ownership.  The ASF licenses this file
//     to you under the Apache License, Version 2.0 (the
//     "License"); you may not use this file except in compliance
//     with the License.  You may obtain a copy of the License at
// 
//       http://www.apache.org/licenses/LICENSE-2.0
// 
//     Unless required by applicable law or agreed to in writing,
//     software distributed under the License is distributed on an
//     "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
//     KIND, either express or implied.  See the License for the
//     specific language governing permissions and limitations
//     under the License.
//

= DevFaqNonSingletonTopComponents
:jbake-type: wiki
:jbake-tags: wiki, devfaq, needsreview
:jbake-status: published
:keywords: Apache NetBeans wiki DevFaqNonSingletonTopComponents
:description: Apache NetBeans wiki DevFaqNonSingletonTopComponents
:toc: left
:toc-title:
:syntax: true

=== How can I change my TopComponent to not be a singleton (NB version up to 6.9)?

The "New Window Component" wizard in the NetBeans IDE generates a link:http://en.wikipedia.org/wiki/Singleton_pattern[singleton] TopComponent.  That's fine for windows that there should only be one of.  Particularly if you are link:DevFaqEditorTopComponent.asciidoc[creating some kind of editor], you will want to create multiple instances of your TopComponent.

==== The really easy way

If you have not already used the *New Window* template to create your TopComponent subclass, don't.

Instead, use _New > JPanel Form_.  Once the new JPanel is created, switch to the Code tab, and replace `extends javax.swing.JPanel` with `extends TopComponent`.  Then do the following things:

* Override `getPersistenceType()`.  
* If you _do not_ want your components reopened on restart
* return `PERSISTENCE_NEVER`&mdash;that is all you need to do to make sure they are not preserved across restarts.
* If you _do_ want your components reopened on restart, then
* return `PERSISTENCE_ONLY_OPENED` from `getPersistenceType()`
* Add the following slightly-cryptic annotation to the class: `@ConvertAsProperties(dtd = "-//com.yourmodule.yourpackage//YourTopComponent//EN", autostore = false)`, replacing the package and class name with your own.  This identifies a DTD.  You do not need to define the DTD.  You just need to give it a unique namespace that nothing else is using.  Package and class name work well for that.
* Add two additional methods (you are not overriding anything and they can be package-private, like serialization methods):
* `void writeProperties(Properties p)` - here we will call `p.put()` passing enough information to reconstruct your component on restart.  If we are editing a file, we might save the path to the file.  If we are viewing a URL, we might save the URL.  If we want to be particularly fastidious, we might save the scroll position, or what line the editor caret was on , or anything else useful to restore the state of our component.
* `void readProperties(Properties p)` - here we will reading whatever keys we wrote out in `writeProperties` and (re)initializing the component to its pre-shutdown state.  This method will be called on startup to restore our component to its pre-shutdown state as best can be done.  If we were, say, editing a file that no longer exists, the appropriate thing to do is throw an exception.  

==== If you already have a generated singleton TopComponent subclass

The good news is that you won't have to write any code -- you'll just have to delete some of the code that was generated for you.

In your TopComponent's .java source file:

* Delete the static `instance` variable, which ought to be declared a few lines above the constructor.
* Make sure your TopComponent class is `public`
* Make sure your TopComponent has a no-argument constructor which is `public`
* Delete the `getDefault()` method (typically somewhere around the middle of the file)
* Delete the `findInstance()` method (which typically follows the `getDefault()` method)
* Update the persistence code which saves your component's state on shutdown and restores it on restart to reopen your component as follows
* Locate the `getPersistenceType` method and change its return value to either `link:http://bits.netbeans.org/dev/javadoc/org-openide-windows/org/openide/windows/TopComponent.html#PERSISTENCE_NEVER[TopComponent.PERSISTENCE_NEVER]` or `link:http://bits.netbeans.org/dev/javadoc/org-openide-windows/org/openide/windows/TopComponent.html#PERSISTENCE_ONLY_OPENED[TopComponent.PERSISTENCE_ONLY_OPENED]` (see below for why).
* If you have methods called `writeReplace()`and an inner class called `ResolvableHelper` (NetBeans 6.8 and earlier):
* Delete the `writeReplace()` method (typically towards the end of the file)
* Delete the `ResolvableHelper` inner class (typically towards the end of the file)
* If you _do not want persistence across restarts_ &mdash; you are returning PERSISTENCE_NEVER from `getPersistenceType()`
* If you have a `@ConvertAsProperties` annotation and `readProperties(Properties)` and `writeProperties(Properties)` methods, delete the annotation and both methods
* If _do want persistence across restarts_ &mdash; you are returning `PERSISTENCE_ONLY_OPENED` from`getPersistenceType()`
* If you already have the `@ConvertAsProperties` annotation and `readProperties(Properties)` and `writeProperties(Properties)` methods just leave them there
* If you do not have the annotation and those methods, implement them as described in the previous section

Next we will need to delete the metadata that registers the component:

* For version 6.9 of NetBeans:
* Delete the settings XML file for your component.  If your component class is `MyWindow` then that file will be in the same folder and will be called `MyWindowSettings.xml`.
* Delete the link:DevFaqWindowsWstcrefAndFriends.asciidoc[wstcrf] (&quot;window system TopComponent reference&quot;) XML file in that folder.  If your component class is `MyWindow` then that file will be named `MyWindowWstcrf.xml`
* Edit your module's [DevFaqModulesLayerFile| layer.xml file] to 
* Remove any references to either of these files (just use Ctrl-F to search for e.g. `MyWindowSettings.xml` and `MyWindowWstcrf.xml`).  They will be in `<file>` tags.
* If you have removed a `<file>` entry, and it was the only entry in that folder, you can remove the XML for parent folder (and its parent if it is now empty, and so forth)
* Find where an Action is registered for to open your (formerly) singleton TopComponent
* _NetBeans 6.9 and later:_  
* Look for an `<file>` registered in `Actions/Window`in the XML file.  It will have an `<attr>` element that refers to your TopComponent class, e.g. `<attr name=&quot;component&quot; methodvalue=&quot;com.foo.MyWindow.findInstance&quot;/>`.  Delete the entire `<file>` entry.
* Look for `<file>` entry for a `.shadow` file in `Actions/Menu` in the XML, with its `originalFile` pointing to the file entry you just deleted.  Delete the `.shadow` `<file>` too.
* _NetBeans 6.8 and earlier:_  
* There will be an `Action` class in your sources which is registered, e.g. `MyWindowAction.java`.  Delete the java source file.
* Look for an `<file>` registered in `Actions/Window`in the XML file.  It will be a `<file>` whose name is the munged fully-qualified class name of the `Action` you just deleted, e.g. `com-foo-MyWindowAction.instance`.  Delete the `<file>` entry for it
* Look for `<file>` entry for a `.shadow` file in `Actions/Menu` in the XML, with its `originalFile` pointing to the file entry you just deleted.  Delete the `.shadow` `<file>` too.

==== Creating And Opening Your TopComponents

Now that you have deleted the actions for your TopComponent, presumably they will be created some other way (for example, from a file's popup menu).  You can create new instances of your TopComponent, open them and give them focus as follows:

[source,java]
----

TopComponent win = new MyTopComponent();
win.open();
win.requestActive(); 
----

If you wrote your persistence code correctly, your components will magically reopen on restart with no further work.

==== What About PERSISTENCE_ALWAYS?

There is one other value you can return from `link:http://bits.netbeans.org/dev/javadoc/org-openide-windows/org/openide/windows/TopComponent.html#getPersistenceType()[TopComponent.getPersistenceType()]`.  That value is `TopComponent.PERSISTENCE_ALWAYS`.

While it is _legal_ to return this value from a non-singleton TopComponent, it is almost never what you want to do.  What will happen if you do this is:

* Every instance of your component that is *ever created* will be persisted on shutdown, _forever_
* Even if it is closed
* Even if nothing can use it, or it represents a file that was deleted, or is in some other way invalid
* Even if no code will ever be able to find it and open it again
* One every restart, _forever_
* Every instance of your component that has _ever existed_ will be read back from disk
* Each one will slow down startup a little bit
* Each one will be wasting disk space

`PERSISTENCE_ALWAYS` is for singleton components that need to be remembered forever across restarts. Don't use it for non-singletons.

==== If you do not have any persistence code, but your components are reopening on restart...

You are returning either `PERSISTENCE_ONLY_OPENED` or `PERSISTENCE_ALWAYS` from `getPersistenceType()`.  If there is no persistence code, but you _are_ returning one of these values, NetBeans will use plain old Java serialization to store and reload your component.

Either use `PERSISTENCE_NEVER` or write persistence code as described above.  Serialization is slower and more fragile than proper persistence, and is never a good option for production code.

=== Apache Migration Information

The content in this page was kindly donated by Oracle Corp. to the
Apache Software Foundation.

This page was exported from link:http://wiki.netbeans.org/DevFaqNonSingletonTopComponents[http://wiki.netbeans.org/DevFaqNonSingletonTopComponents] , 
that was last modified by NetBeans user Cvdenzen 
on 2012-09-18T10:54:57Z.


*NOTE:* This document was automatically converted to the AsciiDoc format on 2018-02-07, and needs to be reviewed.
