{"id":18966943,"url":"https://github.com/link-intersystems/java-swing-mvc-plugin-architecture","last_synced_at":"2025-09-03T20:36:17.571Z","repository":{"id":177770427,"uuid":"652440540","full_name":"link-intersystems/java-swing-mvc-plugin-architecture","owner":"link-intersystems","description":"This repository contains a Java Swing example application that is based on a pluggable MVC architecture. It is an attempt to show how pluggable user interfaces can be implemented, and the basic concepts are not constraint to Java Swing at all.","archived":false,"fork":false,"pushed_at":"2023-07-01T08:33:22.000Z","size":1084,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-06-02T08:45:24.969Z","etag":null,"topics":["example","java","mvc","mvc-architecture","mvc-pattern","plugin","swing"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/link-intersystems.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-06-12T04:51:16.000Z","updated_at":"2024-12-31T10:40:45.000Z","dependencies_parsed_at":null,"dependency_job_id":"e1654688-aaae-4ba6-aeb8-d6e9b489b5d5","html_url":"https://github.com/link-intersystems/java-swing-mvc-plugin-architecture","commit_stats":null,"previous_names":["link-intersystems/java-swing-mvc-plugin-architecture"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/link-intersystems/java-swing-mvc-plugin-architecture","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/link-intersystems%2Fjava-swing-mvc-plugin-architecture","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/link-intersystems%2Fjava-swing-mvc-plugin-architecture/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/link-intersystems%2Fjava-swing-mvc-plugin-architecture/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/link-intersystems%2Fjava-swing-mvc-plugin-architecture/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/link-intersystems","download_url":"https://codeload.github.com/link-intersystems/java-swing-mvc-plugin-architecture/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/link-intersystems%2Fjava-swing-mvc-plugin-architecture/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":273506903,"owners_count":25118066,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-09-03T02:00:09.631Z","response_time":76,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["example","java","mvc","mvc-architecture","mvc-pattern","plugin","swing"],"created_at":"2024-11-08T14:39:09.670Z","updated_at":"2025-09-03T20:36:17.505Z","avatar_url":"https://github.com/link-intersystems.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"![Java CI with Maven](https://github.com/link-intersystems/java-swing-mvc-plugin-architecture/actions/workflows/maven.yml/badge.svg)\n\n# A pluggable Java Swing MVC architecture\n\nThis repository contains a Java Swing example application that is based on \na pluggable MVC architecture. It is an attempt to show how pluggable user interfaces\ncan be implemented, and **the basic concepts are not constraint to Java Swing at all**.\n\n# Table Of Contents\n\n- [MVC](#mvc)\n  - [The original MVC by Trygve Reenskaug](#the-original-mvc-by-trygve-reenskaug)\n  - [Yet another MVC](#yet-another-mvc)\n    - [MVC - wikipedia - english](#mvc---wikipedia---english)\n    - [MVC - wikipedia - german](#mvc---wikipedia---german)\n    - [MVC - Freecodecamp.org](#mvc---freecodecamporg)\n  - [The right MVC!?](#the-right-mvc)\n    - [Discussion about 'my' MVC style](#discussion-about-my-mvc-style)\n      - [Model](#model)\n      - [View](#view)\n      - [Controller](#controller)\n  - [MVC Instantiation](#mvc-instantiation)\n  - [MVC Architecture in this Repository](#mvc-architecture-in-this-repository)\n  - [Make the architecture pluggable](#make-the-architecture-pluggable)\n- [Any Questions](#any-questions)\n\n## MVC\n\nEven though the model-view-controller pattern is widely used and well documented, the way how the different MVC components,\nlike view, model and controller, are instantiated and wired with the infrastructure is not often discussed.\n\nThis repository shows one way of how the MVC instantiation and infrastructure wiring can be done and should\nbe seen as a starting point for discussions about that topic. \n\nYou can also see this repository as a playground to refactor and try out different ways of implementing an MVC pattern.\n\n### The original MVC by Trygve Reenskaug\n\nThe MVC pattern was invented in 1979 by [Trygve Reenskaug](https://en.wikipedia.org/wiki/Trygve_Reenskaug).\n\nIn [his work](https://folk.universitetetioslo.no/trygver/themes/mvc/mvc-index.html) he described the pattern with the following diagram:\n\n![Trygve Reenskaug - MVC](res/mvc-trygve-reenskaug-1979.png)\n\nTrygve Reenskaug did not only introduce the terms model, view controller. He also introduced the term tool \nand mental model. The mental model is the essential part of the diagram, because it makes clear that\na model should be something from the user's perspective. E.g. when you think about a circuit logic your brain\nbuilds a mental model. You probably think of circuits as tiny rectangular entities that have pins to connect them.\nThe MVC model should be close to the way a user thinks about something. So you would find terms like circuit, pin, connector\nand so in the model. He also introduced the term tool and shows that views and controllers together form a tool.\n\nHere is a screenshot from an eclipse application that is used to learn circuit basics. \n\n![MVC - wikipedia - english](res/eclipse-gef-circuit.gif)\n\nYou can see that the eclipse GEF framework is very close to Trygve Reenskaug's definition of MVC.\nThey use tools that a user can pick from a palette. You can also see that the visual representation is close to\nthe way we think about circuits (from a beginners perspective) - our mental model.\n\nWhenever you have a software that can be intuitively used, the software's model is close to the mental model of the user.\nIf not, there is usually a gap between the mental and computer model.\n\nThe last important thing that other diagrams usually omit is the multiplicity, which often leads to the\nassumption that there is always one model, one view and one controller connected. If you believe this way,\nyou should rethink your mental model about the MVC. I wrote a blog named [The MVC pattern implemented with java swing](https://link-intersystems.com/blog/2013/07/20/the-mvc-pattern-implemented-with-java-swing/) back in 2013.\nIn this blog I tried to show that a controller can have more than one model. Usually a controller uses some\nmodels as it's input and some models as it's output.\n\n![MVC - wikipedia - english](res/simple-mvc-link-intersystems-20-07-2023.png)\n\n\n### Yet another MVC\n\nNow that we have a good understanding about the original MVC diagram, we should take a look at other\ndiagrams that one can find on the internet. \n\nThere are a lot of different interpretations of the MVC that led to a lot of different diagrams.\nThose diagrams created a lot of different mental models in the minds of developers. I guess this is the\nreason why developers often implement MVC in different ways and  this can lead to a lot of discussions\nin development teams. \n\nI guess that this issue is not restricted to MVC. We use a lot of terms that often lead to different\nmental models. Therefore, they lead to misunderstanding and discussions. These gaps can significantly slow\ndown the development velocity of a software project.\n\nSince a lot of different views of the MVC has been described over the time. I would like to show you a some, so that you can see what I mean with \"Yet another MVC\".\n\n#### MVC - wikipedia - english\n\nIn the english wikipedia article the MVC pattern is described using a slightly different diagram.\n\n![MVC - wikipedia - english](res/mvc-wiki-en-23.06.2023.png)\n\nAs you can see the term `Tool` that Trygve used does not exist anymore. \nAlso, the associations between the components have directions now. But the biggest difference is that\ncontrollers and view do not have any association between them.\n\n#### MVC - wikipedia - german\n\nIn the german wikipedia article the MVC pattern looks also a little different.\n\n![MVC - wikipedia - english](res/mvc-wiki-de-23.06.2023.png)\n\nHere you can see the association between the controller and the view. And you can also see that there are\ndependencies in both directions, even though the dependency from the view to the controller is a dashed arrow \n(a less strong dependency). The same applies between the view and model.\n\n#### MVC - Freecodecamp.org\n\nFinally, I took a look at yet another description in a [blog post](https://www.freecodecamp.org/news/the-model-view-controller-pattern-mvc-architecture-and-frameworks-explained/) on freecodecamp.org that was written by Rafael D. Hernandez on April 19, 2021.\n\n![MVC - wikipedia - english](res/mvc-freecodecamp.org-23.06.2023.png)\n\nIn this diagram you don't see any dependencies between the view and model at all. The view and model only depend\non the controller.\n\n\n### The right MVC!?\n\nA pattern might evolve over time. It might have to do with technology changes, but it might also be in consequence of \ntranslation errors between different languages that lead to a different understanding. \n\nNo matter what the cause is, we should work hard to keep a common understanding of each term in software development.\nBecause we can not effectively communicate with each other if a term leads to a different mental model in each of us. \n\nSince there are so many different ways one thinks about the MVC pattern. \nI would like to try to consolidate the views and focus on the basic idea of MVC. \nThe diagram I will show you is taken from my blog post [The MVC pattern implemented with Java Swing](https://link-intersystems.com/blog/2013/07/20/the-mvc-pattern-implemented-with-java-swing/) that I wrote in 2013.\nI will explain soon why MVC looks like the following diagram to me and why I think it makes sense compared to the others above.\n\n![MVC - wikipedia - english](res/mvc-link-intersystems-20-07-2023.png)\n\n#### Discussion about 'my' MVC style\n\nWhen I created my mental model about the MVC, while reading all the other explanations about MVC, I tried to focus on software development principles. \nOne principle is the dependency inversion principle. It tells us that\n\n\u003e Abstractions should not depend on details. Details should depend on abstractions.\n\nAs a result I asked myself \n\n\u003e Which of the components is the most abstract and which is the most detailed?\n\n##### Model\n\nThe model is the most abstract, since it only captures a mental model that a user has in his mind. \n\nAs a result the model should not depend on any other components. But wait, there is a dependency between\nthe model and the view. Yes, it's true. But this dependency is an observer relationship where the model is the subject that\nemits events when it's state changes to an observer. The model does not know who the observer is. \nIt only informs someone that it changed. Thus, the dependency is effectively not a direct dependency to the view.\nItself is inversed by applying the dependency inversion principle.\n\n##### View\n\nIn contrast to the model the view is the most detailed component since it defines how a model is presented on the screen.\nSo the view should depend on all other MVC components, but not vice versa. You can also have different views for the same model.\nAs a result of a user interaction the view must execute a controller, so it has a dependency to the controller.\nIt also has a dependency to the model, because it is the visual representation of the model.\n\n##### Controller\n\nThe controller is something in between the view and the model. It implements how models are modifies. Therefore, it has\ndependencies to models. The controller uses some models as it's input and some models as it's output. E.g. when you perform\na login, the controller reads the models that are connected to the username and password fields and updates a user model.\n\n## MVC Instantiation\n\nBut no matter how you see the MVC and which diagram makes more sense to you, there is still one question open in all these diagrams.\n\n\u003e Who instantiates the MVC components and wires them together as well as \n\u003e connects the controllers to the infrastructure or external systems like databases?\n\nThe first though that comes in mind is that there must be some kind of factory. This factory would be the most detail, since it knows all \nthe components and how to instantiate them, and it knows the infrastructure.\n\nSo the first approach would be to just create something, let's name it MVCPart, that takes a ServiceLocator or something and does the instantiation and wiring job.\nBut views open other views and if they do that they must use another MVCPart and this part also needs the service locator in order\nto connect the controllers to the infrastructure. Hmm, should we pass the service locator through the\nMVCParts and the view that it creates? And if we do that it means that the view that opens another view must have a reference to the service locator or\nat least an MVCPart that has a dependency to a service locator. So whoever instantiates the MVCPart must have a dependency to the service locator.\nIf it is a view that was created by another MVCPart then this view must have a dependency to the service locator.\n\nEven when you think that a service locator is not an appropriate way of wiring components with the infrastructure, other ways\nwill lead to the same problems. E.g. if you use a dependency injection framework, the view that opens another view must be injected by the\ndependency injection framework. So when a view opens another it must either call the DI framework or it must use a kind of factory that the DI framework injects.\nIf the `MVCPart`s are instantiated outside the dependency injection framework they still must be wired in some way with the infrastructure \nand the views that instantiate them must somehow get references to the infrastructure components.\n\nBut what if the dependency injection framework just injects the `MVCPart` into a view? Well, this would apply recursively to all MVCParts, because\nan MVCPart instantiates views that can instantiate other views and therefore MVCParts. So all MVCParts must be instantiated when the 'main' or root part is created. \nYou will also have problems when you want to instantiate a MVCPart (model-view-controller) multiple times, because you need more than one instance and\nthese instances can not be qualified since they might be created as a result of a user action. So you can not use e.g. @Qualifier annotations in spring.\n\n### MVC Application State\n\nAnother tricky issue is the application state management.\n\n\u003e Who is responsible for holding the application state and how can MVC components access it to share state between views?\n\nI think there must be some kind of context that can hold the application state. This context should support an event mechanism so that components can register listeners in\norder to get informed when an object will get available, is changed and so on. This context must somehow be global without being a kind of static reference.\n\nAlso, the context might change in the view hierarchy. E.g. there might be some clusters of view components that share a context, but other components that share another instance\nof a context.\n\n\n## MVC Architecture in this Repository\n\nFinally, I came up with the architecture in this repository. Like I said at the beginning \"It is one way of solving the instantiation, wiring and application state issues\".\nSo don't be too cruel with me if you don't like my way. You should see it as a starting point for discussions and this repository as a playground for refactoring.\n\n![MVC Class Model](res/MVC%20Class%20Model.png)\n\nI extended the View from the original MVC and connected it with a `ViewSite`. So my view is a combination of a \"normal\" view that just defines UI components and the MVCPart that I described above.\nOne might argue that it would be better to have a dedicated MVCPart and a separate view, but I wanted to keep the component count small, so I merged both aspects into one class.\n\nA `ViewSite` is a place or location where a `View` is installed. It also provides access to the infrastructure and the application state through a `Context`. The `Context` is nothing more than a place where objects can be stored and retrieved from. \nIt can be used to share application state as well as providing infrastructure services.\n\nEach `View` can declare its own `ViewSite`s where other `View`s can be installed to. So the center of a border layout might be a `ViewSite`.  \nThe parent `View` can either delegate it's `Context` to the child view or create a dedicated `Context`.\n\n![View Site Example](res/view-sites.png)\n\nIn my architecture the `View` also contains the logic of how the MVC model, view (ui components) and controller is instantiated and are wired together. It also\nknows how to `uninstall` or destruct that composition. If a view is moved from one `ViewSite` to another, e.g. using drag and drop, the view must be uninstalled \nand installed at the new view site.\n\nA `ViewLayout` is a description of `ViewSite`s that are available in a particular `View`.\n\nHere is a simple example of how my architecture works:\n\n1. Create a view that should be visible in the main window\n\n        public class ViewSiteView implements View {\n        \n            private final String name;\n        \n            private JPanel panel;\n            private ViewSite viewSite;\n        \n            public ViewSiteView(String name) {\n                this.name = requireNonNull(name);\n            }\n        \n            @Override\n            public void install(ViewSite viewSite) {\n                this.viewSite = viewSite;\n        \n                panel = new JPanel();\n                panel.setLayout(new GridBagLayout());\n        \n                JLabel jLabel = new JLabel(name);\n                GridBagConstraints gbc = new GridBagConstraints();\n                gbc.fill = GridBagConstraints.BOTH;\n                gbc.insets = new Insets(5, 5, 5, 5);\n                panel.add(jLabel, gbc);\n        \n                panel.setBorder(BorderFactory.createLineBorder(new Color(50, 50, 50)));\n        \n                ViewContent viewContent = viewSite.getViewContent();\n                viewContent.setComponent(panel);\n            }\n        \n            @Override\n            public void uninstall() {\n                if (viewSite == null) {\n                    return;\n                }\n        \n                ViewContent viewContent = viewSite.getViewContent();\n                viewContent.setComponent(null);\n        \n                viewSite = null;\n            }\n        }\n\n2.  Create the main window view\n\n        public class ViewSiteExampleView implements View {\n        \n            // Define the view site names\n            public static final String TOP = \"top\";\n            public static final String BOTTOM = \"bottom\";\n            public static final String LEFT = \"left\";\n            public static final String RIGHT = \"right\";\n            public static final String MIDDLE = \"middle\";\n    \n            private ViewSite viewSite;\n            private JFrame frame;\n            private DefaultViewLayout viewLayout;\n    \n            @Override\n            public void install(ViewSite viewSite) {\n                this.viewSite = viewSite;\n    \n                // Create the main view component                \n                frame = new JFrame(\"ViewSite Example\");\n                frame.setSize(640, 480);\n                frame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);\n                frame.addWindowListener(new WindowAdapter() {\n                    @Override\n                    public void windowClosing(WindowEvent e) {\n                        uninstall();\n                    }\n                });\n        \n                frame.setLocationRelativeTo(null);\n        \n                // Create the ViewLayout\n                Container contentPane = frame.getContentPane();\n                Context viewContext = viewSite.getViewContext();\n                viewLayout = createViewLayout(viewContext, contentPane);\n                viewContext.put(ViewLayout.class, viewLayout);\n        \n                // Instal views into the ViewLayout's view sites\n                installView(viewLayout, TOP, \"ViewSite north\");\n                installView(viewLayout, BOTTOM, \"ViewSite south\");\n                installView(viewLayout, LEFT, \"ViewSite west\");\n                installView(viewLayout, RIGHT, \"ViewSite east\");\n                installView(viewLayout, MIDDLE, \"ViewSite center\");\n        \n                // Make the main frame visible by setting the ViewContent\n                ViewContent viewContent = viewSite.getViewContent();\n                viewContent.setComponent(frame);\n            }\n    \n            private DefaultViewLayout createViewLayout(Context viewContext, Container viewContainer) {\n                DefaultViewLayout viewLayout = new DefaultViewLayout(viewContext, viewContainer);\n    \n                viewLayout.addViewSite(TOP, NORTH);\n                viewLayout.addViewSite(BOTTOM, SOUTH);\n                viewLayout.addViewSite(LEFT, WEST);\n                viewLayout.addViewSite(RIGHT, EAST);\n                viewLayout.addViewSite(MIDDLE, CENTER);\n    \n                return viewLayout;\n            }\n    \n            private void installView(ViewLayout viewLayout, String viewSiteName, String areaName) {\n                ViewSiteView viewSiteView = new ViewSiteView(areaName);\n                viewLayout.install(viewSiteName, viewSiteView);\n            } \n        \n            // Uninstall in reverse order\n            @Override\n            public void uninstall() {\n                if (viewSite == null) {\n                    return;\n                }\n        \n                viewLayout.dispose();\n        \n                Context viewContext = viewSite.getViewContext();\n                viewContext.remove(ViewLayout.class);\n                viewLayout = null;\n        \n                ViewContent viewContent = viewSite.getViewContent();\n                viewContent.setComponent(null);\n        \n                frame.dispose();\n                frame = null;\n        \n                viewSite = null;\n            }\n        }\n\n3. Create a main class\n\n       public class ViewSiteExample {\n    \n           public static void main(String[] args) {\n               ViewSiteExampleView viewSiteExampleView = new ViewSiteExampleView();\n    \n               RootViewSite rootViewSite = new RootViewSite(new DefaultContext());\n               viewSiteExampleView.install(rootViewSite);\n           }\n    \n       }\n\n## Make the architecture pluggable\n\nIn order to create a pluggable MVC architecture I'm using Java's [`ServiceLoader`](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/ServiceLoader.html) and interfaces that a\nview uses in order to install other views in it's `ViewLayout`. These other views are located using the\n[`ServiceLoader`](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/ServiceLoader.html). E.g.\n\n\u003e You can find a detailed explanation about the `ServiceLoader` in my blog [A plug-in architecture implemented with java](https://link-intersystems.com/blog/2016/01/02/a-plug-in-architecture-implemented-with-java/) that\n\u003e was published on January 2, 2016 on [link-intersystems.com](https://www.link-intersystems.com).\n\n\n1. Define a `ViewLayoutContribution` interface so that other views can provide a contribution to the view layout.\n\n        public interface ViewLayoutContribution {\n        \n            void install(ViewLayout viewLayout);\n        \n            void uninstall(ViewLayout viewLayout);\n        }\n\n2. The main view loads and installs all views\n\n        private ApplicationViewLayoutMediator initLayoutContributions(ViewLayout viewLayout) {\n            ServiceLoaderAction\u003cViewLayoutContribution\u003e viewContributionAction = new ServiceLoaderAction\u003c\u003e(ViewLayoutContribution.class); \n\n            ApplicationViewLayoutMediator viewLayoutMediator = new ApplicationViewLayoutMediator(viewLayout);\n            viewContributionAction.setTaskActionListener(viewLayoutMediator);\n    \n            ActionTrigger.performAction(this, viewContributionAction);\n    \n            return viewLayoutMediator;\n        }\n   \n   The `ServiceLoaderAction` is an implementation of a [AbstractTaskAction](https://github.com/link-intersystems/lis-commons/blob/lis-commons-1.9.6/lis-commons-swing/src/main/java/com/link_intersystems/swing/action/concurrent/AbstractTaskAction.java) that you can find in my\n   [lis-commons-swing](https://github.com/link-intersystems/lis-commons/tree/main/lis-commons-swing) library that is available in the [maven central repository](https://mvnrepository.com/artifact/com.link-intersystems.commons/lis-commons-swing).\n\n \n3. The action's [`TaskListener`](https://github.com/link-intersystems/lis-commons/blob/lis-commons-1.9.6/lis-commons-swing/src/main/java/com/link_intersystems/swing/action/concurrent/TaskActionListener.java) installs the view\n\n        public class ApplicationViewLayoutMediator implements TaskActionListener\u003cList\u003cViewLayoutContribution\u003e, Void\u003e {\n    \n            private final ViewLayout viewLayout;\n    \n            private final List\u003cViewLayoutContribution\u003e viewLayoutContributions = new ArrayList\u003c\u003e();\n    \n            public ApplicationViewLayoutMediator(ViewLayout viewLayout) {\n                this.viewLayout = requireNonNull(viewLayout);\n            }\n    \n            @Override\n            public void done(List\u003cViewLayoutContribution\u003e result) {\n                result.forEach(this::installView);\n            }\n    \n            private void installView(ViewLayoutContribution viewLayoutContribution) {\n                viewLayoutContribution.install(viewLayout);\n                viewLayoutContributions.add(viewLayoutContribution);\n            }\n    \n            public void dispose() {\n                viewLayoutContributions.forEach(vc -\u003e vc.uninstall(viewLayout));\n            }\n        }\n\n## Any Questions?\n\nIf you have any questions about\n\n- this example application you can [start a discussion](https://github.com/link-intersystems/java-swing-mvc-plugin-architecture/discussions).\n- the MVC architecture in general you can either browse [my answers on stackoverflow](https://stackoverflow.com/search?q=user%3A974186+model-view-controller+swing) or post\n  a new question. or [contact me](https://link-intersystems.com/contact-us/) for trainings and coaching or book a session on [![codementor.io](https://www.codementor.io/m-badges/renlink/book-session.svg)](https://www.codementor.io/@renlink?refer=badge).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flink-intersystems%2Fjava-swing-mvc-plugin-architecture","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flink-intersystems%2Fjava-swing-mvc-plugin-architecture","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flink-intersystems%2Fjava-swing-mvc-plugin-architecture/lists"}