Blogs
A new developer tool can help generate Liferay code and springboard your new Liferay project.
Introduction
One of the great advantages I have being known in the community is really the opportunity to meet, talk and work with talented developers and teams.
Recently the team at ACSoftware announced in the Liferay Community Slack they were working on a new Liferay development tool, and I was fortunate enough to work with them on evaluation and testing. As it is just released, I wanted to introduce the tool because I think it can be a boon towards springboarding your next Liferay project.
Liferay-Gen is a command-line developer tool that leverages Yeoman to help the developer generate a Liferay Workspace, Service Builder modules and corresponding Liferay MVC portlet modules leveraging those services.
Installation
The primary site for the tool is https://liferay-code-generator.acsoftware.it and the Documentation page has the "How to Install" section, but basically it is a two step process after you meet the prerequisites:
- Use the npm install command to install the generator.
- At first launch, enter your license key that you'll have to download.
Basic Usage
The tool works from the command line. Let's start with the simple command to get app info:
$ yo liferay:app ██╗ ██╗███████╗███████╗██████╗ █████╗ ██╗ ██╗ ██████╗ ███████╗███╗ ██╗ ██║ ██║██╔════╝██╔════╝██╔══██╗██╔══██╗╚██╗ ██╔╝ ██╔════╝ ██╔════╝████╗ ██║ ██║ ██║█████╗ █████╗ ██████╔╝███████║ ╚████╔╝█████╗██║ ███╗█████╗ ██╔██╗ ██║ ██║ ██║██╔══╝ ██╔══╝ ██╔══██╗██╔══██║ ╚██╔╝ ╚════╝██║ ██║██╔══╝ ██║╚██╗██║ ███████╗██║██║ ███████╗██║ ██║██║ ██║ ██║ ╚██████╔╝███████╗██║ ╚████║ ╚══════╝╚═╝╚═╝ ╚══════╝╚═╝ ╚═╝╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚══════╝╚═╝ ╚═══╝ Powered By ACSoftware 2021 - v. 1.1.18 info Checking for new updates.... info Checking requirements... info Checking gradle installation... ✔ Gradle 6.8 Found! info Checking java installation... ✔ Java 1.8 Found! info Checking JPM installation... ✔ JPM 4 Found! info Checking Blade installation... ✔ Blade 4 Found! info Checking Node installation... ✔ Node 12.22 Found! Reading projects from:/Users/dnebinger/liferay/Testing/modules info Current version is: 1.1.18 , latest version is: 1.1.18 info No updates found! force .yo-rc.json info Task duration: 2749 ms
Another simple command to try is the help command:
$ yo liferay:help ██╗ ██╗███████╗███████╗██████╗ █████╗ ██╗ ██╗ ██████╗ ███████╗███╗ ██╗ ██║ ██║██╔════╝██╔════╝██╔══██╗██╔══██╗╚██╗ ██╔╝ ██╔════╝ ██╔════╝████╗ ██║ ██║ ██║█████╗ █████╗ ██████╔╝███████║ ╚████╔╝█████╗██║ ███╗█████╗ ██╔██╗ ██║ ██║ ██║██╔══╝ ██╔══╝ ██╔══██╗██╔══██║ ╚██╔╝ ╚════╝██║ ██║██╔══╝ ██║╚██╗██║ ███████╗██║██║ ███████╗██║ ██║██║ ██║ ██║ ╚██████╔╝███████╗██║ ╚████║ ╚══════╝╚═╝╚═╝ ╚══════╝╚═╝ ╚═╝╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚══════╝╚═╝ ╚═══╝ Powered By ACSoftware 2021 - v. 1.1.18 ✔ Data integrity check passed! ------------------------------------------------------------------------------------- yo liferay:app Print info about the liferay generator yo liferay:generate-search-classes Generate search classes for entities yo liferay:help Show help yo liferay:new-mvc-portlet Creates new MVC Portlet yo liferay:new-service-builder Creates new Service Builder Project yo liferay:new-workspace Creates new workspace yo liferay:service-builder Add or Edit entities inside service.xml yo liferay:service-builder-generate-classes Auto generate code for entities for CRUD operations and relationship management! yo liferay:attach Command to be used to hook the generator to an existing workspace
Since we've seen the banner before, I'm going to exclude it going forward. It will be displayed in each command you execute, I just won't be showing them anymore here.
Workspace Usage
The generator is designed to work inside of a Liferay workspace. There are two ways to get started, first is using the new-workspace command:
$ yo liferay:new-workspace ? What is the name of your Workspace? Testing ? What is the global package of this workspace? com.example.testing ? Which version of liferay? dxp-7.3-ga1 info Creating workspace with blade tool... ✔ Workspace creation OK! force .yo-rc.json info Creating yo.rc file... force Testing/.yo-rc.json create Testing/docker-compose-testing info Task duration: 32323 ms
When prompted for the version, you get to pick from the latest versions of 7.0, 7.1, 7.2 and 7.3 CE or DXP. Here I've picked DXP 7.3. You'll get a standard Liferay workspace, empty, but ready to go.
The second option is to attach to an existing workspace, basically putting the pieces in place that the generator will be able to use for executing the commands and providing the context so the generator will work without having to start the workspace over:
$ yo liferay:attach Searching Liferay Worskpace from:/Users/dnebinger/temp/Unattached info settings.gradle found, Liferay Workspace identified! ? What is the global package of this workspace? com.example.unattached ? Which version of liferay? dxp-7.3-ga1 info Creating yo.rc file...
Service Builder Usage
There's a number of commands used to work with Service Builder, so let's look at each one.
First, there's the new-service-builder task which is responsible for starting a new set of Service Builder modules:
$ yo liferay:new-service-builder ? What is the project name? Todo ? What is the Service builder namespace? Todo ? What is the package for your portlet? com.example.testing.todo info Creating service builder with blade tool: blade create -t service-builder -v 7.3 -p com.example.testing.todo Todo Successfully created project Todo in /Users/dnebinger/liferay/Testing/modules ✔ Service Builder project Todo creation OK! force .yo-rc.json force modules/Todo/.yo-rc.json create modules/Todo/Todo-service/src/main/resources/portlet.properties create modules/Todo/Todo-service/src/main/resources/META-INF/resource-actions/default.xml info Task duration: 38008 ms
Next, we can use the service-builder task to manipulate the service.xml and other files:
$ yo liferay:service-builder Reading projects from:/Users/dnebinger/liferay/Testing/modules info Current version is: 1.1.18 , latest version is: 1.1.18 info No updates found! info Creating entity for project:Todo info Reloading configuration of: Todo info Service XML path: /Users/dnebinger/liferay/Testing/modules/Todo/Todo-service/service.xml info Default XML File: /Users/dnebinger/liferay/Testing/modules/Todo/Todo-service/src/main/resources/META-INF/resource-actions/default.xml info Model Hints: /Users/dnebinger/liferay/Testing/modules/Todo/Todo-service/src/main/resources/META-INF/portlet-model-hints.xml info Namespace:Todo info Found an existing service.xml, the changes will continue on that one ? Do you want to edit an existing entity or add new one? AddNew info Creating new entity... ? What is your entity name? Todo ? Do you want to generate standard entity ? (all audit fields with primary key <entity>Id)? Yes ? Has a local service impl? Yes ? Has a remote service impl? Yes ? Has a uuid? Yes ? Do you want to add your entity into Asset? Yes ? Do you want to add workflow fields? Yes ? Choose the workflow fields status, statusByUserId, statusByUserName, statusDate ? What kind of element you want to add? Column ? What is the column name? taskStatus ? What type is it? long ? Do you want to add validation rules or define model hints for your field? No ? Do you want to add a new column? Yes ? What is the column name? task ? What type is it? String ? Do you want to add localization to your field? No ? Do you want to add validation rules or define model hints for your field? Yes ? Which validation rules do you want to add? max-length( hint ) ? What is the value of the validation rule? 4096 ? Do you want to add validation rules or define model hints for your field? No ? Do you want to add a new column? Yes ? What is the column name? dueDate ? What type is it? Date ? Do you want to add validation rules or define model hints for your field? No ? Do you want to add a new column? No ? What kind of element you want to add? Finder ? Whats the finder name? TaskStatus ? What type it returns? Collection ? Whats the finder column name? taskStatus ? Do you want to add a new finder? Yes ? Whats the finder name? DueDate ? What type it returns? Collection ? Whats the finder column name? dueDate ? Do you want to add a new finder? Yes ? Whats the finder name? Owner ? What type it returns? Collection ? Whats the finder column name? userId ? Do you want to add a new finder? No ? What kind of element you want to add? Order ? Order by asc or desc? asc ? Whats your order column name? dueDate:Date ? What kind of element you want to add? Done info Auto-generating finder CompanyId ? Generate Services Code Now? No force .yo-rc.json ✔ Generated sucessfully! info Task duration: 724118 ms
There's a lot going on here, so let's review...
First, it's really a guided question/response cycle, so when you're adding a new column all of the questions are about the column, then you can add finders, order bys, etc.
We start by adding a new entity, Todo. We're then asked if we want the standard audit fields (these would be your company id, group id, create/modified dates, user id and user name) and whether we're adding both local and remote services as well as a UUID. We're also asked if we're going to make the entity an Asset (will require the MVC portlet generation capability for your Asset Renderer support) and whether to enable Workflow. If we say yes to Workflow, we then get to pick the workflow columns to include, I typically just add them all.
Next we can start adding Columns. For each one you're asked for a name and a type and whether you want to add validation rules or hint changes. For my first column I did taskStatus as a long value, so nothing special. For my next column I chose the String type, so it asked me if I wanted it to support localization, in this case I didn't. I also did add a model hint to set the max-length to 4096, this would have been the same if I had manually edited the model-hints.xml file to add the right <hint /> to the column and then regenerated the sources. The available list is quite extensive, so check them out when you are creating your columns.
Next I added a couple of finders, so I had to give them a name, the return type and the finder column tied to the finder.
Using a similar "interview" process, you can add references and relationships and other pieces.
I then selected "Done" as the element to end the cycle, and it asked me if I wanted to generate the services. I said "No" here so I can demonstrate the next command...
Before I do that, though, note that I can re-run this command to add a new entity or edit an existing entity, so this is not a "once and done" generator.
The next step is to build services, and there is a command to help with that:
$ yo liferay:service-builder-generate-classes Reading projects from:/Users/dnebinger/liferay/Testing/modules info Current version is: 1.1.18 , latest version is: 1.1.18 info No updates found! info Creating entity for project:Todo info Reloading configuration of: Todo info Service XML path: /Users/dnebinger/liferay/Testing/modules/Todo/Todo-service/service.xml info Default XML File: /Users/dnebinger/liferay/Testing/modules/Todo/Todo-service/src/main/resources/META-INF/resource-actions/default.xml info Model Hints: /Users/dnebinger/liferay/Testing/modules/Todo/Todo-service/src/main/resources/META-INF/portlet-model-hints.xml info Namespace:Todo info Found an existing service.xml, the changes will continue on that one info Loading portlet-model-hints-xml Starting a Gradle Daemon (subsequent builds will be faster) > Task :modules:Todo:Todo-service:buildService Building Todo Writing src/main/java/com/example/testing/todo/service/persistence/impl/TodoPersistenceImpl.java Writing ../Todo-api/src/main/java/com/example/testing/todo/service/persistence/TodoPersistence.java Writing ../Todo-api/src/main/java/com/example/testing/todo/service/persistence/TodoUtil.java Writing src/main/java/com/example/testing/todo/model/impl/TodoModelImpl.java Writing src/main/java/com/example/testing/todo/model/impl/TodoBaseImpl.java Writing src/main/java/com/example/testing/todo/model/impl/TodoImpl.java Writing ../Todo-api/src/main/java/com/example/testing/todo/model/TodoModel.java Writing ../Todo-api/src/main/java/com/example/testing/todo/model/Todo.java Writing src/main/java/com/example/testing/todo/model/impl/TodoCacheModel.java Writing ../Todo-api/src/main/java/com/example/testing/todo/model/TodoWrapper.java Writing ../Todo-api/src/main/java/com/example/testing/todo/model/TodoSoap.java Writing src/main/java/com/example/testing/todo/service/impl/TodoLocalServiceImpl.java Writing src/main/java/com/example/testing/todo/service/base/TodoLocalServiceBaseImpl.java Writing ../Todo-api/src/main/java/com/example/testing/todo/service/TodoLocalService.java Writing ../Todo-api/src/main/java/com/example/testing/todo/service/TodoLocalServiceUtil.java Writing ../Todo-api/src/main/java/com/example/testing/todo/service/TodoLocalServiceWrapper.java Writing src/main/java/com/example/testing/todo/service/impl/TodoServiceImpl.java Writing src/main/java/com/example/testing/todo/service/base/TodoServiceBaseImpl.java Writing ../Todo-api/src/main/java/com/example/testing/todo/service/TodoService.java Writing ../Todo-api/src/main/java/com/example/testing/todo/service/TodoServiceUtil.java Writing ../Todo-api/src/main/java/com/example/testing/todo/service/TodoServiceWrapper.java Writing src/main/java/com/example/testing/todo/service/http/TodoServiceHttp.java Writing src/main/java/com/example/testing/todo/service/http/TodoServiceSoap.java Writing src/main/resources/META-INF/module-hbm.xml Writing src/main/resources/META-INF/portlet-model-hints.xml Writing ../Todo-api/src/main/java/com/example/testing/todo/exception/TodoException.java Writing ../Todo-api/src/main/java/com/example/testing/todo/exception/NoSuchTodoException.java Writing src/main/java/com/example/testing/todo/service/persistence/impl/constants/TodoPersistenceConstants.java Writing src/main/resources/META-INF/sql/indexes.sql Writing src/main/resources/META-INF/sql/tables.sql Writing src/main/resources/META-INF/sql/tables.sql Writing src/main/resources/service.properties Deprecated Gradle features were used in this build, making it incompatible with Gradle 7.0. Use '--warning-mode all' to show the individual deprecation warnings. See https://docs.gradle.org/6.6.1/userguide/command_line_interface.html#sec:command_line_warnings BUILD SUCCESSFUL in 9s 1 actionable task: 1 executed ✔ Build service executed succesfully, starting generation... info Entity has column companyId and the relative finder! info Entity Primary Key Getter is: getTodoId() info --------- GENERATING IN LOCAL SERVICE ------------- info Local Service Not found imports: [ 'import com.example.testing.todo.exception.TodoException;', 'import com.example.testing.todo.exception.NoSuchTodoException;', 'import com.example.testing.todo.model.Todo;', 'import com.example.testing.todo.service.persistence.TodoUtil;', 'import com.liferay.portal.kernel.util.Validator;', 'import com.liferay.portal.kernel.language.LanguageUtil;', 'import com.liferay.portal.kernel.search.Indexable;', 'import com.liferay.portal.kernel.search.IndexableType;', 'import com.liferay.portal.kernel.service.ServiceContext;', 'import com.liferay.portal.kernel.exception.PortalException;', 'import com.liferay.asset.kernel.service.AssetEntryLocalServiceUtil;', 'import com.liferay.counter.kernel.service.CounterLocalServiceUtil;', 'import com.liferay.portal.kernel.model.Group;', 'import com.liferay.portal.kernel.model.ResourceConstants;', 'import com.liferay.portal.kernel.model.User;', 'import com.liferay.portal.kernel.service.UserLocalServiceUtil;', 'import com.liferay.portal.kernel.service.GroupLocalServiceUtil;', 'import com.liferay.portal.kernel.service.ResourceLocalServiceUtil;', 'import com.liferay.portal.kernel.log.Log;', 'import com.liferay.portal.kernel.log.LogFactoryUtil;', 'import java.util.Locale;', 'import java.util.ResourceBundle;', 'import java.util.List;' ] info Adding logger declaration! info Search for method check info method not found, generating at line 68 info Search for method createNewTodo info method not found, generating at line 125 info Search for method deleteTodo info method not found, generating at line 135 info Search for method saveOrUpdateTodo info method not found, generating at line 161 info Search for method removeTodoRelationships info method not found, generating at line 224 info Search for method beforeCheckTodo info method not found, generating at line 234 info Search for method beforeSaveOrUpdateTodo info method not found, generating at line 247 info Search for method afterSaveOrUpdateTodo info method not found, generating at line 261 info Search for method customValidation info method not found, generating at line 275 info Search for method BeforeDeleteTodo info method not found, generating at line 291 info Search for method AfterDeleteTodo info method not found, generating at line 300 info Search for method findAll info method not found, generating at line 309 info Search for method getTodoCount info method not found, generating at line 321 info Search for method getTodoList info method not found, generating at line 325 info Search for method findByTaskStatus info method not found, generating at line 335 info Search for method findByDueDate info method not found, generating at line 339 info Search for method findByOwner info method not found, generating at line 343 info Search for method findByCompanyId info method not found, generating at line 347 info --------- GENERATING IN SERVICE ------------- info ServiceImpl Not found imports: [ 'import com.liferay.portal.kernel.log.Log;', 'import com.liferay.portal.kernel.log.LogFactoryUtil;', 'import com.liferay.portal.kernel.service.ServiceContext;', 'import com.liferay.portal.kernel.exception.PortalException;', 'import com.liferay.portal.kernel.security.auth.PrincipalException;', 'import com.liferay.portal.kernel.security.permission.ActionKeys;', 'import com.liferay.portal.kernel.security.permission.resource.PortletResourcePermission;', 'import com.liferay.portal.kernel.security.permission.resource.ModelResourcePermission;', 'import com.liferay.portal.kernel.security.permission.resource.PortletResourcePermissionFactory;', 'import com.liferay.portal.kernel.security.permission.resource.ModelResourcePermissionFactory;', 'import com.liferay.portal.kernel.security.permission.ActionKeys;', 'import com.example.testing.todo.model.Todo;', 'import com.example.testing.todo.constants.TodoConstants;', 'import com.example.testing.todo.constants.action.TestingActionKeys;', 'import com.example.testing.todo.exception.TodoException;', 'import java.util.HashMap;', 'import java.util.List;' ] info Adding logger declaration! info Adding Portlet resource declaration! info Adding Model resource declaration! info Search for method deleteTodo info method not found, generating at line 66 info Search for method deleteTodo info method not found, generating at line 88 info Search for method findAll info method not found, generating at line 102 info Search for method saveOrUpdateTodo info method not found, generating at line 123 info Model Todo not found in permission definition, creating it! info Creating content/Language.properties... force .yo-rc.json create modules/Todo/Todo-api/src/main/java/com/example/testing/todo/constants/TodoConstants.java create modules/Todo/Todo-api/src/main/java/com/example/testing/todo/constants/TestingTodoPortletKeys.java create modules/Todo/Todo-api/src/main/java/com/example/testing/todo/constants/action/TestingActionKeys.java create modules/Todo/Todo-service/src/main/java/com/example/testing/todo/internal/security/permission/resource/TodoModelResourcePermissionRegistrar.java create modules/Todo/Todo-service/src/main/java/com/example/testing/todo/internal/security/permission/resource/TodoPortletResourcePermissionRegistrar.java > Task :modules:Todo:Todo-service:buildService Building Todo Writing ../Todo-api/src/main/java/com/example/testing/todo/service/TodoLocalService.java Writing ../Todo-api/src/main/java/com/example/testing/todo/service/TodoLocalServiceUtil.java Writing ../Todo-api/src/main/java/com/example/testing/todo/service/TodoLocalServiceWrapper.java Writing ../Todo-api/src/main/java/com/example/testing/todo/service/TodoService.java Writing ../Todo-api/src/main/java/com/example/testing/todo/service/TodoServiceUtil.java Writing ../Todo-api/src/main/java/com/example/testing/todo/service/TodoServiceWrapper.java Writing src/main/java/com/example/testing/todo/service/http/TodoServiceHttp.java Writing src/main/java/com/example/testing/todo/service/http/TodoServiceSoap.java Writing src/main/resources/service.properties Deprecated Gradle features were used in this build, making it incompatible with Gradle 7.0. Use '--warning-mode all' to show the individual deprecation warnings. See https://docs.gradle.org/6.6.1/userguide/command_line_interface.html#sec:command_line_warnings BUILD SUCCESSFUL in 4s 1 actionable task: 1 executed ✔ Build service executed successfully, starting generation... info Task duration: 21160 ms
This command does more than just invoke the Gradle task to build the services, it also injects methods into the EntityLocalServiceImpl and EntityServiceImpl classes. It also builds in support for permissions, workflow, exposing the finders, etc.
Another command is the generate-search-classes, although you need the Professional license to use this feature. If you have it, the generator will ask for the fields that should be indexed, and it will generate the classes to support all of the indexing and search functionality:
$ yo liferay:generate-search-classes Reading projects from:/Users/dnebinger/liferay/Testing/modules info Current version is: 1.1.18 , latest version is: 1.1.18 info No updates found! info Creating entity for project:Todo info Reloading configuration of: Todo info Service XML path: /Users/dnebinger/liferay/Testing/modules/Todo/Todo-service/ service.xml info Default XML File: /Users/dnebinger/liferay/Testing/modules/Todo/Todo-service/ src/main/resources/META-INF/resource-actions/default.xml info Model Hints: /Users/dnebinger/liferay/Testing/modules/Todo/Todo-service/src/ main/resources/META-INF/portlet-model-hints.xml info Namespace:Todo info Found an existing service.xml, the changes will continue on that one ? Please select Summary title field: task:String ? Please select Summary content field: task:String ? Please select search fields: userId:long, taskStatus:long, task:String, dueDate:Date force .yo-rc.json info Generating [object Object] TodoIndexField.java info Generating [object Object] TodoKeywordQueryContributor.java info Generating [object Object] TodoModelDocumentContributor.java info Generating [object Object] TodoModelIndexerWriterContributor.java info Generating [object Object] TodoModelSummaryContributor.java info Generating [object Object] TodoSearchRegistrar.java create modules/Todo/Todo-service/src/main/java/com/example/testing/todo/search/todo/ field/TodoIndexerField.java create modules/Todo/Todo-service/src/main/java/com/example/testing/todo/search/todo/ TodoKeywordQueryContributor.java create modules/Todo/Todo-service/src/main/java/com/example/testing/todo/search/todo/ TodoModelDocumentContributor.java create modules/Todo/Todo-service/src/main/java/com/example/testing/todo/search/todo/ TodoModelIndexerWriterContributor.java create modules/Todo/Todo-service/src/main/java/com/example/testing/todo/search/todo/ TodoModelSummaryContributor.java create modules/Todo/Todo-service/src/main/java/com/example/testing/todo/search/todo/ TodoSearchRegistrar.java info Task duration: 46688 ms
Portlet Usage
So you can definitely stop here if you want to. Creating the service layer is often more challenging than creating a portlet, so you might not need or want the generated portlet. I prefer to include the generated portlet if only to get the full Asset Rendering support for the custom entities so I don't have to build them myself. I may not drop the portlet on a page, but at least the Asset Renderer will work.
To create the portlet, we use the new-mvc-portlet command:
$ yo liferay:new-mvc-portlet Reading projects from:/Users/dnebinger/liferay/Testing/modules info Removing old projects configuration:todo-web info Current version is: 1.1.18 , latest version is: 1.1.18 info No updates found! ? What is the name of your new module? todo-web ? What is the package for your portlet? com.example.testing.todo.internal.portlet ? What is the category of your new portlet? sample ? Do you want your module will be instancable? Yes ? Do you want to create a panel app for your portlet? Yes ? Which type of panel app category you want to insert?: Liferay Panel App Categories ? Insert panel app category name: SITE_ADMINISTRATION_CONTENT ? Do you want to create jsp for CRUD operations? Yes info Creating entity for project:Todo info Reloading configuration of: Todo info Service XML path: /Users/dnebinger/liferay/Testing/modules/Todo/Todo-service/service.xml info Default XML File: /Users/dnebinger/liferay/Testing/modules/Todo/Todo-service/src/main/resources/META-INF/resource-actions/default.xml info Model Hints: /Users/dnebinger/liferay/Testing/modules/Todo/Todo-service/src/main/resources/META-INF/portlet-model-hints.xml info Namespace:Todo ? Choose the entity for jsp creation Todo ? Choose the entity fields you want to show in list view todoId, taskStatus, task, dueDate ? Choose the column to use for sorting dueDate info Press <enter> if you want to skip relationships... ? Choose the entity fields you want to show in the input html form taskStatus, task, dueDate ? Crud portlet needs the generation of search indexes classes, do you want to generate it? No info Creating Toolbar Portlet... force .yo-rc.json create modules/todo-web/build.gradle create modules/todo-web/.gitignore force modules/todo-web/.yo-rc.json create modules/todo-web/bnd.bnd create modules/todo-web/src/main/resources/content/Language.properties create modules/todo-web/src/main/resources/portlet.properties create modules/todo-web/src/main/resources/META-INF/resource-actions/default.xml create modules/todo-web/src/main/java/com/example/testing/todo/internal/portlet/constants/Todo-WebPortletKeys.java create modules/todo-web/src/main/java/com/example/testing/todo/internal/web/internal/security/permission/resource/Todo-WebModelPermission.java create modules/todo-web/src/main/java/com/example/testing/todo/internal/web/internal/security/permission/resource/Todo-WebPermission.java create modules/todo-web/src/main/java/com/example/testing/todo/internal/util/TodoComparator.java create modules/todo-web/src/main/java/com/example/testing/todo/internal/portlet/Todo-WebPortletPanelApp.java force modules/toolbar-portlet/.yo-rc.json create modules/toolbar-portlet/build.gradle create modules/toolbar-portlet/bnd.bnd create modules/toolbar-portlet/src/main/resources/content/Language.properties create modules/toolbar-portlet/src/main/resources/META-INF/resources/init.jsp create modules/toolbar-portlet/src/main/resources/META-INF/resources/view.jsp create modules/toolbar-portlet/src/main/java/com/example.testing.toolbar.portlet/application/list/ToolbarPanelCategory.java create modules/toolbar-portlet/src/main/java/com/example.testing.toolbar.portlet/constants/ToolbarPanelCategoryKeys.java create modules/toolbar-portlet/src/main/java/com/example.testing.toolbar.portlet/util/SearchManagementToolbarDisplayContext.java create modules/todo-web/src/main/java/com/example/testing/todo/internal/portlet/Todo-WebPortlet.java create modules/todo-web/src/main/resources/META-INF/resources/init.jsp create modules/todo-web/src/main/resources/META-INF/resources/view.jsp create modules/todo-web/src/main/resources/META-INF/resources/edit.jsp create modules/todo-web/src/main/resources/META-INF/resources/entry_actions.jsp create modules/todo-web/src/main/resources/META-INF/resources/management_toolbar.jsp create modules/todo-web/src/main/resources/META-INF/resources/search_columns.jspf create modules/todo-web/src/main/resources/META-INF/resources/view_todo_list.jsp info Task duration: 81797 ms
So now I can generate and deploy the modules. The portlet dropped on a page looks like:
This shows the list, and either the edit or the add button in the
upper right gets you to the form:
Since I also asked for the Panel App with the Site Content
category, I can also see it in the control panel:
Are these UIs ready for production deployment? No, I don't think
so. I was originally thinking my due date would just be a date, not a
timestamp. The task status would be a number, but likely I'd make them
constants representing states such as "Pending",
"Completed", "Cancelled", etc.
So yeah, there would be changes I'd like to make, but I'm starting out so far ahead than if I had to create this interface all on my own.
Conclusion
Well this concludes the tour, please check your seats to ensure you have all of your personal belongings before exiting the train...
So I like this tool, I like what it generates and it really can be a time saver for launching a new Service Builder-based system.
Like all tools (including Liferay's), it is opinionated, but it has to be to support pulling all of the pieces together and have them work. And although it is opinionated, it doesn't feel like it is opinionated in a bad way, just a different way.
The generated code is complete and will compile for you and you can deploy it, all pretty much unchanged from the generated version. It's also of a sound quality, too, and in the version I reviewed I didn't find any significant defects.
So I encourage you to give it a try for your next Liferay project and see just how it might save you a big chunk of time...
Let me know what you think in the comments below...