75. How to
75.1. Enterprise Architect client generation
We are going to show you how to generate source code from an Enterprise Architect diagram using CobiGen.
75.1.1. Prerequisites
If CobiGen_Templates is not already imported into your workspace, follow the next steps:
-
Click on the Eclipse’s menu File > Import > Existing Projects into Workspace and browse to select the
workspaces/main/CobiGen_Templates
directory. -
Click Finish and you should have the CobiGen_Templates as a new project in Eclipse’s workspace.
Also verify that you have the latest templates of CobiGen. Your templates folder must contain the crud_java_ea_uml
folder.
If you do not see it, please follow the next steps:
-
Download the accumulative patch.
-
Open the zip file and extract its content inside the root folder of your Devonfw distribution Devon-dist_2.4.0/
After following those steps correctly, you should have the latest version of the templates ready to use.
75.1.2. Generation
In this tutorial, we are going to generate the entity infrastructure using as input a class diagram, modelled with Enterprise Architect (EA). First, create a class diagram, an example is shown on figure below:
When you are finished, you will have to export that UML diagram into an XMI version 2.1 file. This is the file format that CobiGen understands. See below a figure showing this process:
To open that window, see this tutorial.
After having that exported file, change its extension from xmi
to xml
. Then create an devon4j project and import the exported file into the core
of your devon4j project.
Now we are going to start the generation, right-click your exported file and select CobiGen > Generate, finally select the entity infrastructure increment:
After following all these steps, your generated files should be inside src\main\java
folder. If you want an XMI example, you will find it here.
75.2. Angular 8 Client Generation
The generation can create a full Angular 8 client using the devon4ng-application-template package located at workspaces/examples folder of the distribution. For more details about this package, please refer here.
You can also try out the katacoda tutorial for angular client generation.
Take into account that the TypeScript merging for CobiGen needs Node 6 or higher to be installed at your machine.
|
Note
|
This is a short introduction to the Angular generation. For a deeper tutorial including the generation of the backend, we strongly recommend you to follow this document. |
75.2.1. Requisites
Install yarn globally:
npm install -g yarn
75.2.2. Angular 8 workspace
The output location of the generation can be defined editing the cobigen.properties file located at crud_angular_client_app/templates folder of the CobiGen_Templates project.
By default, the output path would be into the devon4ng-application-template folder at the root of the devon4j project parent folder:
root/ |- devon4ng-application-template/ |- devon4j-project-parent/ |- core/ |- server/
However, this path can be changed, for example to src/main/client folder of the devon4j project:
relocate: ./src/main/client/${cwd}
root/ |- devon4j-project-parent/ |- core/ |- src |- main |- client |- server/
Once the output path is chosen, copy the files of DEVON4NG-APPLICATION-TEMPLATE repository into this output path.
75.2.3. Install Node dependencies
Open a terminal into devon4ng-application-template copied and just run the command:
yarn
This will start the installation of all node packages needed by the project into the node_modules folder.
75.2.4. Generating
From an Eto object, right click, CobiGen → Generate will show the CobiGen wizard relative to client generation:
Check all the increments relative to Angular:
|
Note
|
The Angular devon4j URL increment is only needed for the first generations however, checking it again on next generation will not cause any problem. |
As we done on other generations, we click Next to choose which fields to include at the generation or simply clicking Finish will start the generation.
75.2.5. Routing
Due to the nature of the TypeScript merger, currently is not possible to merge properly the array of paths objects of the routings at app.routing.ts file so, this modification should be done by hand on this file. However, the import related to the new component generated is added.
This would be the generated app-routing.module
file:
import { Routes, RouterModule } from '@angular/router';
import { LoginComponent } from './login/login.component';
import { AuthGuard } from './shared/security/auth-guard.service';
import { InitialPageComponent } from './initial-page/initial-page.component';
import { HomeComponent } from './home/home.component';
import { SampleDataGridComponent } from './sampledata/sampledata-grid/sampledata-grid.component';
//Routing array
const appRoutes: Routes = [{
path: 'login',
component: LoginComponent
}, {
path: 'home',
component: HomeComponent,
canActivate: [AuthGuard],
children: [{
path: '',
redirectTo: '/home/initialPage',
pathMatch: 'full',
canActivate: [AuthGuard]
}, {
path: 'initialPage',
component: InitialPageComponent,
canActivate: [AuthGuard]
}]
}, {
path: '**',
redirectTo: '/login',
pathMatch: 'full'
}];
export const routing = RouterModule.forRoot(appRoutes);
Adding the following into the children object of home
, will add into the side menu the entry for the component generated:
{
path: 'sampleData',
component: SampleDataGridComponent,
canActivate: [AuthGuard],
}
import { Routes, RouterModule } from '@angular/router';
import { LoginComponent } from './login/login.component';
import { AuthGuard } from './shared/security/auth-guard.service';
import { InitialPageComponent } from './initial-page/initial-page.component';
import { HomeComponent } from './home/home.component';
import { SampleDataGridComponent } from './sampledata/sampledata-grid/sampledata-grid.component';
//Routing array
const appRoutes: Routes = [{
path: 'login',
component: LoginComponent
}, {
path: 'home',
component: HomeComponent,
canActivate: [AuthGuard],
children: [{
path: '',
redirectTo: '/home/initialPage',
pathMatch: 'full',
canActivate: [AuthGuard]
}, {
path: 'initialPage',
component: InitialPageComponent,
canActivate: [AuthGuard]
}, {
path: 'sampleData',
component: SampleDataGridComponent,
canActivate: [AuthGuard],
}]
}, {
path: '**',
redirectTo: '/login',
pathMatch: 'full'
}];
export const routing = RouterModule.forRoot(appRoutes);
75.2.6. JWT Authentication
If you are using a back end server with JWT Authentication (there is a sample in workspaces/folder called sampleJwt) you have to specify the Angular application to use this kind of authentication.
By default the variable is set to ‘csrf’ but you can change it to JWT by going to the Enviroment.ts and setting security: 'jwt'
.
75.2.7. Running
First of all, run your devon4j java server by right clicking over SpringBootApp.java Run As → Java Application. This will start to run the SpringBoot server. Once you see the Started SpringBoot in XX seconds, the backend is running.
Once the the server is running, open a Devon console at the output directory defined previously and run:
ng serve --open
This will run the Angular 8 application at:
http://localhost:4200
Once finished, the browser will open automatically at the previous localhost URL showing the Angular 8 application, using the credentials set at the devon4j java server you will be able to access.
75.3. Ionic client generation
We are going to show you how to generate a CRUD Ionic application from an ETO using CobiGen.
|
Note
|
This is a short introduction to the Ionic generation. For a deeper tutorial including the generation of the backend, we strongly recommend you to follow this document. |
75.3.1. Prerequisites
Before starting, make sure you already have in your computer:
If CobiGen_Templates are not already downloaded, follow the next steps:
-
Right click on any file of your workspace CobiGen > Update Templates and now you are able to start the generation.
-
If you want to adapt them, click Adapt Templates and you should have the CobiGen_Templates as a new project in Eclipse’s workspace.
After following those steps correctly, you should have the latest version of the templates ready to use.
75.3.2. Generation
We are going to generate the CRUD into a sample application that we have developed for
testing this functionality. It is present on your workspaces/examples
folder (devon4ng-ionic-application-template). If you do not see it, you can clone or download it from here.
After having that sample app, please create an devon4j project and then start implementing the ETO: You will find an example here.
As you can see, TableEto
contains 3 attributes: 2 of them are Long
and the third one TableState
is an enum that you will find
here.
The Ionic generation works fine for any Java primitive attribute (Strings, floats, chars, boolean…) and enums. However, if you want to use your own objects, you should
override the toString()
method, as explained here.
The attributes explained above will be used for generating a page that shows a list. Each item of that list will show the values of those attributes.
For generating the files:
-
Right click your ETO file and click on CobiGen > Generate as shown on the figure below.
-
Select the Ionic increments for generating as shown below. Increments group a set of templates for generating different projects.
-
Ionic List used for generating the page containing the list.
-
Ionic devon4ng environments is for stating the server path.
-
Ionic i18n used for generating the different language translations for the translationService (currently English and Spanish).
-
Ionic routing adds an app-routing.module.ts file to allow navigation similar to the one available in Angular.
-
Ionic theme generates the variables.scss file which contains variables to style the application.
-
|
Note
|
By default, the generated files will be placed inside "devon4ng-ionic-application-template", next to the root of your project’s folder. See the image below to know where they are generated. For changing the generation path and the name of the application go to CobiGen_Templates/crud_ionic_client_app/cobigen.properties. |
Now that we have generated the files, lets start testing them:
-
First change the SERVER_URL of your application. For doing that, modify src/environments/environments.ts, also modify src/environments/environments.android.ts (android) and src/environments/environments.prod.ts (production) if you want to test in different environments.
-
Check that there are no duplicated imports. Sometimes there are duplicated imports in src/app/app.module.ts. This happens because the merger of CobiGen prefers to duplicate rather than to delete.
-
Run
npm install
to install all the required dependencies. -
Run
`ionic serve
on your console.
After following all these steps your application should start. However, remember that you will need your server to be running for access to the list page.
75.3.3. Running it on Android
To run the application in an android emulated device, it is necessary to have Android Studio and Android SDK. After its installation, the following commands have to be run on your console:
-
npx cap init "name-for-the-app (between quotes)" "id-for-the-app (between quotes)"
-
ionic build --configuration=android
. To use this command, you must add an android build configuration at angular.json"build": { ... "configurations": { ... "android": { "fileReplacements": [ { "replace": "src/environments/environment.ts", "with": "src/environments/environment.android.ts" } ] }, } }
-
npx cap add android
-
npx cap copy
-
npx cap open android
The last steps are done in Android studio: make the project, make the app, build and APK and run in a device.
75.4. Implementing a new Plug-in
New plug-ins can implement an input reader, a merger, a matcher, a trigger interpreter, and/or a template engine as explained here.
|
Note
|
It is discouraged to have |
75.4.1. Plugin Activator
Each plug-in has to have an plug-in activator class implementing the interface GeneratorPluginActivator
from the core-api. This class will be used to load the plug-in using the PluginRegistry as explained here. This class implements two methods:
-
bindMerger()
→ returns a mapping of merge strategies and its implementation to be registered. -
bindTriggerInterpreter()
→ returns the trigger interpreters to be provided by this plug-in.
Both methods create and register instances of mergers and trigger interpreters to be provided by the new plug-in.
75.4.2. Adding TriggerInterpreter
The trigger interpreter has to implement the TriggerInterpreter interface from the core. The trigger interpreter defines the type for the new plugin and creates new InputReader and new Matcher objects.
75.4.3. Adding InputReader
The input reader is responsible of read the input object and parse it into FreeMarker models. The input reader must be implemented for the type of the input file. If there is any existent plugin that has the same file type as input, there will be no need to add a new input reader to the new plug-in.
InputReader Interface
The interface needed to add a new input reader is defined at the core. Each new sub plug-in must implements this interface if is needed an input reader for it.
The interface implements the basic methods that an input reader must have, but if additional methods are required, the developer must add a new interface that extends the original interface InputReader.java from the core-api and implement that on the sub plug-in.
The methods to be implemented by the input reader of the new sub plugin are:
| Method | Return Type | Description |
|---|---|---|
|
boolean |
This function will be called if matching triggers or matching templates should be retrieved for a given input object. |
|
Map<String, Object> |
This function should create the FreeMarker object model from the given input. |
|
boolean |
States whether the given input object combines multiple input objects to be used for generation. |
|
List<Object> |
Will return the set of combined input objects if the given input combines multiple input objects. |
|
Map<String, Object> |
This method returns available template methods from the plugins as Map. If the plugin which corresponds to the input does not provide any template methods an empty Map will be returned. |
|
List<Object> |
Will return the set of combined input objects if the given input combines multiple input objects. |
Model Constants
The Input reader will create a model for FreeMarker. A Freemarker model must
have variables to use them at the .ftl
template file. Refer to Java Model to see the FreeMarker model example for java input files.
Registering the Input Reader
The input reader is an object that can be retrieved using the correspondent get
method of the trigger interpreter object. The trigger interpreter object is
loaded at the eclipse plug-in using the load plug-in method explained
here.
That way, when the core needs the input reader, only needs to call that getInputReader
method.
75.4.4. Adding Matcher
The matcher implements the MatcherInterpreter interface from the core-api.
Should be implemented for providing a new input matcher. Input matcher are
defined as part of a trigger and provide the ability to restrict specific
inputs to a set of templates.
This restriction is implemented with a MatcherType enum
.
E.g JavaPlugin
private enum MatcherType {
/** Full Qualified Name Matching */
FQN,
/** Package Name Matching */
PACKAGE,
/** Expression interpretation */
EXPRESSION
}
Furthermore, matchers may provide several variable assignments, which might be dependent on any information of the matched input and thus should be resolvable by the defined matcher.
E.g JavaPlugin
private enum VariableType {
/** Constant variable assignment */
CONSTANT,
/** Regular expression group assignment */
REGEX
}
75.4.5. Adding Merger
The merger is responsible to perform merge action between new output with the existent data at the file if it already exists. Must implement the Merger interface from the core-api. The implementation of the Merge interface must override the following methods:
| Method | Return Type | Description |
|---|---|---|
|
String |
Returns the type, this merger should handle. |
|
String |
Merges the patch into the base file. |
Is important to know that any exception caused by the merger must throw a MergeException from the core-api to the eclipse-plugin handle it.
75.4.6. Changes since Eclipse / Maven 3.x
Since version 3.x the Eclipse and Maven plugins of CobiGen utilize the Java ServiceLoader
mechanic to find and register plugins at runtime. To enable a new plugin to be discovered by this mechanic the following steps are needed:
-
create the file
META-INF/services/com.capgemini.cobigen.api.extension.GeneratorPluginActivator
containing just the full qualified name of the class implementing theGeneratorPluginActivator
interface, if the plugin provides aMerger
and/or aTriggerInterpreter
-
create the file
META-INF/services/com.capgemini.cobigen.api.extension.TextTemplateEngine
containing just the full qualified name of the class implementing theTextTemplateEngine
interface, if provided by the plugin -
include
META-INF
into the target bundle (i.e. the folderMETA-INF
has to be present in the target jar file)
-
to properly include the plugin into the current system and use existing infrastructure, you need to add the plugin as a module in
/cobigen/pom.xml
(in case of aMerger
/TriggerInterpreter
providing plugin) and declare that as the plugin’s parent in it’s ownpom.xml
via
<parent> <groupId>com.capgemini</groupId> <artifactId>cobigen-parent</artifactId> <version>dev-SNAPSHOT</version> </parent>
or /cobigen/cobigen-templateengines/pom.xml
(in case of a Merger
/TriggerInterpreter
providing plugin) and declare that as the plugin’s parent in it’s own pom.xml
via
<parent>
<groupId>com.capgemini</groupId>
<artifactId>cobigen-tempeng-parent</artifactId>
<version>dev-SNAPSHOT</version>
</parent>
If the plugin provides both just use the /cobigen/pom.xml
.
-
The dependencies of the plugin are included in the bundle
-
To make the plugin available to the Eclipse plugin it must be included into the current
compositeContent.xml
andcompositeArtifacts.xml
files. Both files are located inhttp://de-mucevolve02/files/cobigen/updatesite/{experimental|nightly|stable}
. To do so, add an<child>
entry to the<children>
tag in both files and adapt thesize
attribute to match the new number of references. Thelocation
attribute of the new<child>
tag needs to be the artifact id of the pluginspom.xml
.
Deployment
For the Maven Plugin
Execute mvn clean deploy
from the plugins project folder. You need to configure write access to the devon nexus (e.g in the CobiGen IDE via the variables-customized
script)
For the Eclipse Plugin
Depending on the kind of release you want to publish you can chose from the following maven profiles:
-
experimental
is for, as the name suggests, experimental snapshot builds. In case of new plugins this is a good place to upload first drafts. -
nightly
is for periodically CI deployment. -
stable
is solely for releases.
E.g. you want an experimental release you need to follow these steps:
# Builds the Manifest and bundles the dependencies
mvn clean package bundle:bundle -Pp2-bundle
# Uses the created bundle and builds a p2 update site for it. Do NOT use clean
mvn install bundle:bundle -Pp2-bundle,p2-build-mars,p2-build-experimental p2:site
# Uploads the p2 update site to the experimental repository. Do NOT use clean
mvn deploy -Pp2-build-mars,p2-build-experimental -Dp2.upload=experimental
You need write access to the iCSD file server configured (e.g in the CobiGen IDE via the variables-customized
script).
75.5. Introduction to CobiGen external plug-ins
Since September of 2019, a major change on CobiGen has taken place. CobiGen is written in Java code and previously, it was very hard for developers to create new plug-ins in other languages.
Creating a new plug-in means:
-
Being able to parse a file in that language.
-
Create a human readable model that can be used to generate templates (by retrieving properties from the model).
-
Enable merging files, so that user’s code does not get removed.
For the Java plug-in it was relatively easy. As you are inside the Java world, you can use multiple utilities or libraries in order to get the AST or to merge Java code. With this new feature, we wanted that behaviour to be possible for any programming language.
75.5.1. General intuition
Below you will find a very high level description of how CobiGen worked in previous versions:
Basically, when a new input file was sent to CobiGen, it called the input reader to create a model of it (see here an example of a model). That model was sent to the template engine.
Afterwards, the template engine generated a new file which had to be merged with the original one. All this code was implemented in Java.
On the new version, we have implemented a handler (ExternalProcessHandler
) which connects through TCP/IP connection to a server (normally on localhost:5000). This server can be implemented in any language (.Net, Node.js, Python…) it just needs to implement a REST API defined here. The most important services are the input reading and merging:
CobiGen acts as a client that sends requests to the server in order to read the input file and create a model. The model is returned to the template engine so that it generates a new file. Finally, it is sent back to get merged with the original file.
75.5.2. How to create new external plug-in
The creation of a new plug-in consists mainly in three steps:
-
Creation of the server (external process).
-
Creation of a CobiGen plug-in.
-
Creation of templates.
Server (external process)
The server can be programmed in any language that is able to implement REST services endpoints. The API that needs to implement is defined with this contract. You can paste the content to https://editor.swagger.io/ for a better look.
We have already created a NestJS server that implements the API defined above. You can find the code here which you can use as an example.
As you can see, the endpoints have the following naming convention: processmanagement/todoplugin/nameOfService
where you will have to change todo
to your plug-in name (e.g. rustplugin, pyplugin, goplugin…)
When implementing service getInputModel
which returns a model from the input file there are only two restrictions:
-
A
path
key must be added. Its value can be the full path of the input file or just the file name. It is needed because in CobiGen there is a batch mode, in which you can have multiple input objects inside the same input file. You do not need to worry about batch mode for now. -
On the root of your model, for each found key that is an object (defined with brackets
[{}]
), CobiGen will try to use it as an input object. For example, this could be a valid model:{ "path": "example/path/employee.entity.ts" "classes": [ { "identifier": "Employee", "modifiers": [ "export" ], "decorators": [ { "identifier": { "name": "Entity", "module": "typeorm" }, "isCallExpression": true } ], "properties": [ { "identifier": "id", ... ... ... }] "interfaces": [{ ... }] }
For this model, CobiGen would use as input objects all the classes
and interfaces
defined. On the templates we would be able to do model.classes[0].identifier
to get the class name. These input objects depend on the language, therefore you can use any key.
In order to test the server, you will have to deploy it on your local machine (localhost), default port is 5000. If that port is already in use, you can deploy it on higher port values (5001, 5002…). Nevertheless, we explain later the testing process as you need to complete the next step before.
|
Important
|
Your server must accept one argument when running it. The argument will be the port number (as an integer). This will be used for CobiGen in order to handle blocked ports when deploying your server. Check this code to see how we implemented that argument on our NestJS server. |
CobiGen plug-in
You will have to create a new CobiGen plug-in that connects to the server. But do not worry, you will not have to implement anything new. We have a CobiGen plug-in template available, the only changes needed are renaming files and setting some properties on the pom.xml. Please follow these steps:
-
Get the CobiGen plug-in template from here. It is a template repository (new GitHub feature), so you can click on "Use this template" as shown below:
-
Name your repo as
cobigen-name-plugin
wherename
can be python, rust, go… In our case we will create anest
plug-in. It will create a repo with only one commit which contains all the needed files. -
Clone your just created repo and import folder
cobigen-todoplugin
as a Maven project on any Java IDE, though we recommend you devonfw ;) -
Rename all the
todoplugin
folders, files and class names tonameplugin
. In our casenestplugin
. In Eclipse you can easily rename by right clicking and then refactor → rename:
|
Note
|
We recommend you to select all the checkboxes |
-
Remember to change in
src/main/java
andsrc/test/java
all the package, files and class names to use your plug-in name. The final result would be: -
Now we just need to change some strings, this is needed for CobiGen to register all the different plugins (they need unique names). In class
TodoPluginActivator
(in our caseNestPluginActivator
), change all thetodo
to your plug-in name. See below the 3 strings that need to be changed: -
Finally, we will change some properties from the
pom.xml
of the project. These properties define the server (external process) that is going to be used:-
Inside
pom.xml
, press Ctrl + F to perform a find and replace operation. Replace alltodo
with your plugin name: -
We are going to explain the server properties:
-
artifactId: This is the name of your plug-in, that will be used for a future release on Maven Central.
-
plugin.name: does not need to be changed as it uses the property from the
artifactId
. When connecting to the server, it will send a request tolocalhost:5000/{plugin.name}plugin/isConnectionReady
, that is why it is important to use an unique name for the plug-in. -
server.name: This defines how the server executable (.exe) file will be named. This .exe file contains all the needed resources for deploying the server. You can use any name you want.
-
server.version: You will specify here the server version that needs to be used. The .exe file will be named as
{server.name}-{server.version}.exe
. -
server.url: This will define from where to download the server. We really recommend you using NPM which is a package manager we know it works well. We explain here how to release the server on NPM. This will download the .exe file for Windows.
-
server.url.linux: Same as before, but this should download the .exe file for Linux systems. If you do not want to implement a Linux version of the plug-in, just use the same URL from Windows or MacOS.
-
server.url.macos: Same as before, but this should download the .exe file for MacOS systems. If you do not want to implement a MacOS version of the plug-in, just use the same URL from Linux or Windows.
-
-
75.5.3. Testing phase
Now that you have finished with the implementation of the server and the creation of a new CobiGen plug-in, we are going to explain how you can test that everything works fine:
-
Deploy the server on port 5000.
-
Run
mvn clean test
on the CobiGen-plugin or run the JUnit tests directly on Eclipse.-
If the server and the plug-in are working properly, some tests will pass and other will fail (we need to tweak them).
-
If every test fails, something is wrong in your code.
-
-
In order to fix the failing tests, go to
src/test/java
. The failing tests make use of sample input files that we added in sake of example:
Replace those files (on src/test/resources/testadata/unittest/files/…
) with the correct input files for your server.
75.5.4. Releasing
Now that you have already tested that everything works fine, we are going to explain how to release the server and the plug-in.
Release the server
We are going to use NPM to store the executable of our server. Even though NPM is a package manager for JavaScript, it can be used for our purpose.
-
Get the CobiGen server template from here. It is a template repository (new GitHub feature), so you can click on "Use this template" as shown below:
-
Name your repo as
cobigen-name-server
wherename
can be python, rust, go… In our case we will create anest
plug-in. It will create a repo with only one commit which contains all the needed files. -
Clone your just created repo and go to folder
cobigen-todo-server
. It will just contain two files: ExternalProcessContract.yml is the OpenAPI definition which you can modify with your own server definition (this step is optional), and package.json is a file needed for NPM in order to define where to publish this package:{ "name": "@devonfw/cobigen-todo-server", "version": "1.0.0", "description": "Todo server to implement the input reader and merger for CobiGen", "author": "CobiGen Team", "license": "Apache" }
Those are the default properties. This would push a new package cobigen-todo-server
on the devonfw
organization, with version 1.0.0. We have no restrictions here, you can use any organization, though we always recommend devonfw.
|
Note
|
Remember to change all the todo to your server name.
|
-
Add your executable file into the
cobigen-todo-server
folder, just like below. As we said previously, this .exe is the server ready to be deployed.cobigen-template-server/ |- cobigen-todo-server/ |- ExternalProcessContract.yml |- package.json |- todoserver-1.0.0.exe
-
Finally, we have to publish to NPM. If you have never done it, you can follow this tutorial. Basically you need to login into NPM and run:
cd cobigen-todo-server/ npm publish --access=public
|
Note
|
To release Linux and MacOS versions of your plug-in, just add the suffix into the package name (e.g. @devonfw/cobigen-todo-server-linux )
|
That’s it! You have published the first version of your server. Now you just need to modify the properties defined on the pom of your CobiGen plug-in. Please see next section for more information.
Releasing CobiGen plug-in
-
Change the pom.xml to define all the properties. You can see below a final example for
nest
:... <groupId>com.devonfw.cobigen</groupId> <artifactId>nestplugin</artifactId> <name>CobiGen - Nest Plug-in</name> <version>1.0.0</version> <packaging>jar</packaging> <description>CobiGen - nest Plug-in</description> <properties> <!-- External server properties --> <plugin.name>parent</plugin.name> <server.name>nestserver</server.name> <server.version>1.0.0</server.version><EMAIL_ADDRESS><EMAIL_ADDRESS><EMAIL_ADDRESS>...
-
Deploy to Maven Central.
75.5.5. Templates creation
After following above steps, we now have a CobiGen plug-in that connects to a server (external process) which reads your input files, returns a model and is able to merge files.
However, we need a key component for our plug-in to be useful. We need to define templates:
-
Fork our CobiGen main repository, from here and clone it into your PC. Stay in the
master
branch and import into your IDEcobigen-templates\templates-devon4j
. Set the Java version of the project to 1.8 if needed. -
Create a new folder on
src/main/templates
, this will contain all your templates. You can use any name, but please use underscores as separators. In our case, we created a foldercrud_typescript_angular_client_app
to generate an Angular client from a TypeORM entity (NodeJS entity). -
Inside your folder, create a
templates
folder. As you can see below, the folder structure of the generated files starts here (the sources). Also we need a configuration filetemplates.xml
that should be on the same level astemplates/
folder. For now, copy and paste atemplates.xml
file from any of the templates folder. -
Start creating your own templates. Our default templates language is Freemarker, but you can also use Velocity. Add the extension to the file (
.ftl
) and start developing templates! You can find useful documentation here. -
After creating all the templates, you need to modify
context.xml
which is located on the root ofsrc/main/templates
. There you need to define a trigger, which is used for CobiGen to know when to trigger a plug-in. I recommend you to copy and paste the following trigger:<trigger id="crud_typescript_angular_client_app" type="nest" templateFolder="crud_typescript_angular_client_app"> <matcher type="fqn" value="([^\.]+).entity.ts"> <variableAssignment type="regex" key="entityName" value="1"/> <variableAssignment type="regex" key="component" value="1"/> <variableAssignment type="constant" key="domain" value="demo"/> </matcher> </trigger>
-
Change
templateFolder
to your templates folder name.id
you can use any, but it is recommendable to use the same as the template folder name.type
is theTRIGGER_TYPE
we defined above on theNestPluginActivator
class. Onmatcher
just change thevalue
:([^\.]+).entity.ts
means that we will only accept input files that contain "anyString.entity.ts". This improves usability, so that users only generate using the correct input files. You will find more info aboutvariableAssignment
here. -
Finally, is time to configure
templates.xml
. It is needed for organizing templates into increments, please take a look into this documentation.
Testing templates
-
When you have finished your templates you will like to test them. On the templates-devon4j
pom.xml
remove the SNAPSHOT from the version (in our case the version will be 3.1.8). Runmvn clean install -DskipTests
on the project. We skip tests because you need special permissions to download artifacts from our Nexus. Remember the version that has just been installed:
|
Note
|
We always recommend using the devonfw console, which already contains a working Maven version. |
-
Now we have your last version of the templates ready to be used. We need to use that latest version in CobiGen. We will use the CobiGen CLI that you will find in your cloned repo, at
cobigen-cli/cli
. Import the project into your IDE. -
Inside the project, go to
src/main/resources/pom.xml
. This pom.xml is used on runtime in order to install all the CobiGen plug-ins and templates. Add there your latest templates version and the previously created plug-in: -
Afterwards, run
mvn clean install -DskipTests
and CobiGen will get your plug-ins. Now you have three options to test templates:-
Using Eclipse run as:
-
Inside Eclipse, you can run the CobiGen-CLI as a Java application. Right click class
CobiGenCLI.java
→ run as → run configurations… and create a new Java application as shown below: -
That will create a
CobiGenCLI
configuration where we can set arguments to the CLI. Let’s first begin with showing the CLI version, which should print a list of all plug-ins, including ours.... name:= propertyplugin version = 2.0.0 name:= jsonplugin version = 2.0.0 name:= templates-devon4j version = 3.1.8 name:= nestplugin version = 1.0.0 ...
-
If that worked, now you can send any arguments to the CLI in order to generate with your templates. Please follow this guide that explains all the CLI commands.
-
-
Modify the already present JUnit tests on the CLI project: They test the generation of templates from multiple plug-ins, you can add your own tests and input files.
-
Use the CLI jar to execute commands:
-
The
mvn clean install -DskipTests
command will have created a Cobigen.jar inside your target folder (cobigen-cli/cli/target). Open the jar with any unzipper and extract to the current location class-loader-agent.jar, cobigen.bat and cg.bat: -
Now you can run any CobiGen CLI commands using a console. This guide explains all the CLI commands.
-
-
75.5.6.
In this guide we will explain how to generate a new WebApi project from an OpenAPI 3.0.0 specification. This means that we are going to use a “contract first” strategy. This is going to be possible due to these type of files that contain all the information about entities, operations, etc…
In order to make it work we are using CobiGen, a powerful tool for generating source code. CobiGen allows users to generate all the structure and code of the components, helping to save a lot of time otherwise waisted on repetitive tasks.
First, we will install the devonfw-ide. It is a tool that will setup your IDE within minutes. Please follow the install guide here.
We are going to use the template of devon4net as a base to generate all the code, so what we have to do now is to download said template using the following steps.
First of all you have to set up all the environment for .NET, you can do this using the following tutorial. Next we are going to create a new folder where we want to have the WebAPI project, lastly we are going to open the terminal there.
Type the following:
dotnet new -i Devon4Net.WebAPI.Template
and then:
dotnet new Devon4NetAPI
In order to let CobiGen generate all the files, we first have to make some modifications to our OpenAPI file.
It is obligatory to put the “x-rootpackage” tag to indicate where CobiGen will place the generated files as well as the "x-component" tags for each component, keep in mind that due to CobiGen’s limitations each component must have its own entity.
You can read more information about how to configure your OpenAPI file and a working example here.
Cobigen allow us to generate the files in two different ways. One of them is using Eclipse which it can be done by using the its grafical interface. The other way to generate the code is using the Cobigen CLI tool.
In order to generate the files using Eclipse we need to follow some simple steps.
First we are going to import our basic devon4net WebAPI Project into Eclipse. to do so open Eclipse with the “eclipse-main.bat” file that can be found in the devon distribution root folder. Once we are inside of Eclipse we go to File > Open projects from file system… and, under "Directory", search for your project.
Next we copy our OpenAPI file into the root folder of the project.
And then we right click on OpenAPI file and then select CobiGen > Generate… It will display a window like this:
To select all .NET features choose CRUD devon4net Server otherwise you can select only those that interest you.
Ones you select all the files that you want to generate, click on the “Finish” button to generate all the source code.
In ordet to generate the files using the Cobigen CLI it is needed to do the following steps:
-
Go to devonfw distribution folder
-
Run console.bat, this will open a console.
-
Go to the folder you downloaded the devon4net template and your yml file.
-
Run the command:
cobigen generate {yourOpenAPIFile}.yml
-
A list of increments will be printed so that you can start the generation. It has to be selected CRUD devon4net Server increment.
Cobigen is generating an empty context that has to be filled with manualy in order to be able to work with the database. The context can be found in [Project_Name]/Devon4Net.WebAPI.Implementation/Domain/Database/CobigenContext.cs.
After the configuration of the database, open a terminal in path: [Project_Name]/Devon4Net.Application.WebAPI and then type:
dotnet run
This will deploy our application in our localhost with the port 8082, so when you click here (https://localhost:8082/swagger) you can see, in swagger, all the services and the data model.
75.6. How to update CobiGen
In order to update CobiGen from our devonfw distribution, we have two options:
-
Open Eclipse, click on Help → Check for updates
-
Select all the CobiGen plugins listed and click on Next.
If this option is not working properly, then you can try the second option:
-
Open Eclipse, click on Help → About Eclipse IDE:
-
Click on Installation details:
-
Select all the CobiGen plugins and click on Update:
After the update process finishes, remember to restart Eclipse.
75.6.1. Updating templates:
To update your CobiGen templates to the latest version, you just need to do one step:
-
Right click any file on your package explorer, click on CobiGen → Update templates, then click on download:
Now you will have the latest templates ready!
Unresolved directive in cobigen.wiki/master-cobigen.asciidoc - include::howto-Cobigen-CLI-generation.asciidoc[leveloffset=2]
75.7. End to End POC Code generation using Entity class
This article helps to create a sample application using cobigen.
75.7.1. Prerequisites
Download and install devonnfw IDE here,
75.7.2. Steps to create a Sample Project using Cobigen
The HOW_TO is divided in 2 parts:
-
BE-Back End generator (DB + DAO + services) – CONTRACT FIRST APPROACH
-
FE-Front End generator (Web App Angular + Ionic App) – CONTRACT FIRST APPROACH
So, ready to go! We’re going to start from the BE part …
Back End
run \devonfw-ide-scripts-3.2.4\eclipse-main.bat
It will open eclipse
create a project using below command from the command prompt
devon java create com.example.domain.myapp
Import the project to eclipse as maven project
Click FINISH
Now We have the following 4 projects.
BEFORE to start to create an Entity class, remember to create the tables !
-
Create a new SQL file (i.e: V0005CreateTables-ItaPoc.sql) inside myapp-__core and insert the following script:
CREATE TABLE EMPLOYEE (
id BIGINT auto_increment, modificationCounter INTEGER NOT NULL,
employeeid BIGINT auto_increment,
name VARCHAR(255),
surname VARCHAR(255),
email VARCHAR(255),
PRIMARY KEY (employeeid)
);
WARNING: please note that there are 2 underscore in the name !
-
Now create another SQL file (i.e: V0006__PopulateTables-ItaPoc.sql) and add following script about the INSERT in order to populate the table created before
WARNING: please note that there are 2 underscore in the name !
INSERT INTO EMPLOYEE (id, modificationCounter, employeeid, name, surname,email) VALUES (1, 1, 1, 'Albert','Miller','albert.miller@example.com');
INSERT INTO EMPLOYEE (id, modificationCounter, employeeid, name, surname,email) VALUES (2, 2, 2, 'Wills','Smith', 'wills.smith@example.com');
INSERT INTO EMPLOYEE (id, modificationCounter, employeeid, name, surname,email) VALUES (3, 3, 3, 'Jaime','Thomas', 'jaime.thomas@example.com');
Let’s create the Entity Class for the code generation
-
Create a package employeemanagement.dataaccess.api under the folder myapp-core. Note: It is important to follow this naming convention for CobiGen to work properly.
-
Now create a JPA Entity class in this package
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Column;
@Entity
@javax.persistence.Table(name = "EMPLOYEE")
public class EmployeeEntity {
@Column(name = "EMPLOYEEID")
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long employeeId;
@Column(name = "NAME")
private String name;
@Column(name = "SURNAME")
private String surname;
@Column(name = "EMAIL")
private String email;
}
then generate getters and setters for all attributes …
-
Use Cobigen to generate code. Right click on EmployeeEntity. CobiGen → Generate
It will ask you to download the templates, click on update:
It will automatically download the latest version of CobiGen_Templates.
Attention: If you want to adapt the CobiGen_Templates, (normally this is not neccessary), you will find at the end of this document a tutorial on how to import them and adapt them!
-
Click on all the option selected as below:
-
Click on finish. Below Screen would be seen. Click on continue
The entire BE layer structure having CRUD operation methods will be auto generated.
Some classes will be generated on the api part (myapp-api), normally it will be interfaces, as shown below:
Some other classes will be generated on the core part (myapp-core), normally it will be implementations as shown below:
BEFORE to generate the FE, please start the Tomcat server to check that BE Layer has been generated properly.
To start a server you just have to right click on SpringBootApp.java → run as → Spring Boot app
BE DONE
Last but not least: We make a quick REST services test !
See in the application.properties the TCP Port and the PATH
Now compose the Rest service URL:
service class path>/<service method path>
-
<server> refers to server with port no. (ie: localhost:8081)
-
<app> is in the application.propeeties (empty in our case, see above)
-
<rest service class path> refers to EmployeemanagementRestService: (i.e: /employeemanagement/v1)
-
<service method path>/employee/{id} (i.e: for getEmployee method)
URL of getEmployee for this example is:
for all employees
http://localhost:8081/services/rest/employeemanagement/v1/employee/search
for the specific employee
http://localhost:8081/services/rest/employeemanagement/v1/employee/1
Now download Postman to test the rest services.
Once done, you have to create a POST Request for the LOGIN and insert in the body the JSON containing the username and password waiter
Once done with success (Status: 200 OK) …
… We create a NEW GET Request in order to get one employee
Now you can click
Now you ‘ve to check that response has got Status: 200 OK and to see the below Employee
Now that We have successfully tested the BE is time to go to create the FE !
Front End
Let’s start now with angular Web and then Ionic app.
Angular Web App
-
To generate angular structure, download or clone devon4ng-application-template from
https://github.com/devonfw/devon4ng-application-template
-
Once done, right click on EmployeeEto.java file present under the package com.devonfw.poc.employeemanagement.logic.api.to
-
Click on Finish
-
The entire ANGULAR structure has been auto generated. The generated code will be merged to the existing.
-
IMPORTANT now you have to add in the app-routing.module.ts file the next content, as a child of HomeComponent, in order to enable the route of the new generated component
,\{
path: 'employee',
component: EmployeeGridComponent,
canActivate: [AuthGuard],
},
Following picture explain where to place the above content:
-
Open the command prompt and execute devon yarn install from the base folder, which would download all the required libraries..
-
Check the file environment.ts if the server path is correct. (for production you will have to change also the environment.prod.ts file)
In order to do that it’s important to look at the application.properties to see the values as PATH, TCP port etc …
For example in this case the URL should be since the context path is empty the server URLS should be like:
export const environment = {
production: false,
restPathRoot: 'http://localhost:8081/',
restServiceRoot: 'http://localhost:8081/services/rest/',
security: 'jwt'
};
Warning: REMEMBER to set security filed to jwt , if it is not configured already.
-
Now run the ng serve -o command to run the Angular Application.
-
If the command execution is successful, the below screen will appear and it would be automatically redirected to the url:
http://localhost:4200/login
WebApp DONE
Ionic Mobile App
-
To generate Ionic structure, download or clone devon4ng-application-template from
https://github.com/devonfw/devon4ng-ionic-application-template
-
Once done, Right click on the EmployeeEto as you already did before in order to use CobiGen.
-
Click on the selected options as seen in the screenshot:
-
Click on Finish
-
The entire ionic structure will be auto generated.
-
Change the server url (with correct serve url) in environment.ts, environment.prod.ts and environment.android.ts files (i.e: itapoc\devon4ng-ionic-application-template\src\environments\).
The angular.json file inside the project has already a build configuration for android.
-
Run npm install in the root folder to download the dependecies
-
Run ionic serve
-
Once the execution is successful
-
Mobile App DONE*
So: well done
Starting from an Entity class you’ve successfully generated the Back-End layer (REST, SOAP, DTO, Spring services, Hibernate DAO), the Angular Web App and the Ionic mobile App!
Since We’re going to create apk remember the following pre-conditions:
-
Now, open cmd and type the path where your devon4ng-ionic-application-template project is present.
-
Run the following commands:
-
npx cap init
-
ionic build --configuration=android
-
npx cap add android
-
npx cap copy
-
npx cap open android
-
-
Build the APK using Android studio.
You can find your apk file in
/devon4ng-ionic-application-template/android/app/build/outputs/apk/debug
75.7.3. Adapt CobiGen_Templates
After following this tutorial, you will have the CobiGen_Templates downloaded on your local machine. To import these templates you need to do the following:
Right click in any part of the package explorer, then click on CobiGen → Adapt templates
Click Ok:
Now the CobiGen_Templates project will be automatically imported into your workspace, as shown on the image below:
Now you just need to change the Java version of the project to JRE 1.8. Right click on the JRE system library, and then on Properties:
Now change the version to Java 1.8
Now you have successfully imported the CobiGen templates. If you want to edit them, you will find them in the folder src/main/templates. For instance, the Java templates are located here:
Now you can adapt the templates as much as you want. Documentation about this can be found on:
https://github.com/devonfw/tools-cobigen/wiki/Guide-to-the-Reader
75.8. End to End POC Code generation using OpenAPI
This article helps to create a sample application using cobigen.
75.8.1. Prerequisites
Download and install devonnfw IDE here,
75.8.2. Steps to create a Sample Project using Cobigen
The HOW_TO is divided in 2 parts:
-
BE-Back End generator (DB + DAO + services) – CONTRACT FIRST APPROACH
-
FE-Front End generator (Web App Angular + Ionic App) – CONTRACT FIRST APPROACH
So, ready to go! We’re going to star
t from the BE part …
Back End
run \devonfw-ide-scripts-3.2.4\eclipse-main.bat
It will open eclipse
create a project using below command from the command prompt
devon java create com.example.domain.myapp
Import the project to eclipse as maven project
Click FINISH
Now We have the following 4 projects.
BEFORE to start to create an Entity class, remember to create the tables !
-
Create a new SQL file (i.e: V0005CreateTables_ItaPoc.sql) inside jwtsample-__core and insert the following script:
CREATE TABLE EMPLOYEE (
id BIGINT auto_increment, modificationCounter *INTEGER* *NOT* *NULL*,
employeeid BIGINT auto_increment,
name VARCHAR(255),
surname VARCHAR(255),
email VARCHAR(255),
PRIMARY KEY (employeeid)
);
WARNING: please note that there are 2 underscore in the name !
-
Now create another SQL file (i.e: V0006__PopulateTables-ItaPoc.sql) and add following script about the INSERT in order to populate the table created before
WARNING: please note that there are 2 underscore in the name !
INSERT INTO EMPLOYEE (id, modificationCounter, employeeid, name, surname,email) VALUES (1, 1, 1, 'Albert','Miller','albert.miller@example.com');
INSERT INTO EMPLOYEE (id, modificationCounter, employeeid, name, surname,email) VALUES (2, 2, 2, 'Angelo','Gonzalez', 'angelo.gonzalez@example.com');
INSERT INTO EMPLOYEE (id, modificationCounter, employeeid, name, surname,email) VALUES (3, 3, 3, 'Jaime','King', 'jaime.king@example.com');
Let’s create the yml file for the code generation
-
Now create a new file devonfw.yml in the root of your core folder. This will be our OpenAPI contract, like shown below. Then, copy the contents of this file into your OpenAPI. It defines some REST service endpoints and a EmployeeEntity with its properties defined.
Important: if you want to know how to write an OpenAPI contract compatible with CobiGen, please read this tutorial.
-
Right click devonfw.yml. CobiGen → Generate
It will ask you to download the templates, click on update:
It will automatically download the latest version of CobiGen_Templates.
Attention: If you want to adapt the CobiGen_Templates, (normally this is not neccessary), you will find at the end of this document a tutorial on how to import them and adapt them!
-
Click on all the option selected as below:
-
Click on finish. Below Screen would be seen. Click on continue
The entire BE layer structure having CRUD operation methods will be auto generated.
Some classes will be generated on the api part (jwtsample-api), normally it will be interfaces, as shown below:
Some other classes will be generated on the core part (jwtsample-core), normally it will be implementations as shown below:
BEFORE to generate the FE, please start the Tomcat server to check that BE Layer has been generated properly.
To start a server you just have to right click on SpringBootApp.java → run as → Spring Boot app
BE DONE
Last but not least: We make a quick REST services test !
See in the application.properties the TCP Port and the PATH
Now compose the Rest service URL:
service class path>/<service method path>
-
<server> refers to server with port no. (ie: localhost:8081)
-
<app> is in the application.propeeties (empty in our case, see above)
-
<rest service class path> refers to EmployeemanagementRestService: (i.e: /employeemanagement/v1)
-
<service method path>/employee/{id} (i.e: for getEmployee method)
URL of getEmployee for this example is:
For all employees
http://localhost:8081/services/rest/employeemanagement/v1/employee/search
For the specific employee
http://localhost:8081/services/rest/employeemanagement/v1/employee/1
Now download Postman to test the rest services.
Once done, you have to create a POST Request for the LOGIN and insert in the body the JSON containing the username and password waiter
Once done with success (Status: 200 OK) …
… We create a NEW POST Request and We copy the Authorization Bearer field (see above) and We paste it in the Token field (see below)
and specific the JSON parameters for the pagination of the Request that We’re going to send:
Now you can click
Now you ‘ve to check that response has got Status: 200 OK and to see the below list of Employee
Now that We have successfully tested the BE is time to go to create the FE !
Front End
Let’s start now with angular Web and then Ionic app.
Angular Web App
-
To generate angular structure, download or clone *devon4ng-application-template* from
https://github.com/devonfw/devon4ng-application-template
-
Once done, right click on devonfw.yml again (the OpenAPI contract). CobiGen → Generate
-
Click on the selected options as seen in the screenshot:
-
Click on Finish
-
The entire ANGULAR structure has been auto generated. The generated code will be merged to the existing.
-
IMPORTANT now you have to add in the app-routing.module.ts file the next content, as a child of HomeComponent, in order to enable the route of the new generated component
,\{
path: 'employee',
component: EmployeeGridComponent,
canActivate: [AuthGuard],
},
Following picture explain where to place the above content:
-
Open the command prompt and execute devon yarn install from the base folder, which would download all the required libraries..
-
Check the file environment.ts if the server path is correct. (for production you will have to change also the environment.prod.ts file)
In order to do that it’s important to look at the application.properties to see the values as PATH, TCP port etc …
For example in this case the URL should be since the context path is empty the server URLS should be like:
export const environment = {
production: false,
restPathRoot: 'http://localhost:8081/',
restServiceRoot: 'http://localhost:8081/services/rest/',
security: 'jwt'
};
Warning: REMEMBER to set security filed to jwt , if it is not configured already.
-
Now run the *ng serve -o* command to run the Angular Application.
-
If the command execution is successful, the below screen will appear and it would be automatically redirected to the url:
http://localhost:4200/login
WebApp DONE
Ionic Mobile App
-
To generate Ionic structure, download or clone *devon4ng-application-template* from
https://github.com/devonfw/devon4ng-ionic-application-template
-
Once done, Right click on the devonfw.yml as you already did before in order to use CobiGen.
-
Click on the selected options as seen in the screenshot:
-
Click on Finish
-
The entire ionic structure will be auto generated.
-
Change the server url (with correct serve url) in environment.ts, environment.prod.ts and environment.android.ts files (i.e: itapoc\devon4ng-ionic-application-template\src\environments\).
The angular.json file inside the project has already a build configuration for android.
-
Run npm install in the root folder to download the dependecies
-
Run ionic serve
-
Once the execution is successful
-
Mobile App DONE*
So: well done
Starting from an Entity class you’ve successfully generated the Back-End layer (REST, SOAP, DTO, Spring services, Hibernate DAO), the Angular Web App and the Ionic mobile App!
Since We’re going to create apk remember the following pre-conditions:
-
Now, open cmd and type the path where your devon4ng-ionic-application-template project is present.
-
Run the following commands:
-
npx cap init
-
ionic build --configuration=android
-
npx cap add android
-
npx cap copy
-
npx cap open android
-
-
Build the APK using Android studio.
You can find your apk file in
/devon4ng-ionic-application-template/android/app/build/outputs/apk/debug
75.8.3. Adapt CobiGen_Templates
After following this tutorial, you will have the CobiGen_Templates downloaded on your local machine. To import these templates you need to do the following:
Right click in any part of the package explorer, then click on CobiGen → Adapt templates
Click Ok:
Now the CobiGen_Templates project will be automatically imported into your workspace, as shown on the image below:
Now you just need to change the Java version of the project to JRE 1.8. Right click on the JRE system library, and then on Properties:
Now change the version to Java 1.8
Now you have successfully imported the CobiGen templates. If you want to edit them, you will find them in the folder src/main/templates. For instance, the Java templates are located here:
Now you can adapt the templates as much as you want. Documentation about this can be found on:
https://github.com/devonfw/tools-cobigen/wiki/Guide-to-the-Reader
75.9. Enable Composite Primary Keys in Entity
In order to enable Composite Primary Keys in entity in CobiGen, the below approach is suggested
The templates in cobigen have been enhanced to support Composite primary keys while still supporting the default devonfw/Cobigen values with Long id.
Also, the current generation from Entity still holds good - right click from an Entity object, CobiGen → Generate will show the CobiGen wizard relative to the entity generation.
After generating, below example shows how composite primary keys can be enabled.
@Entity
@Table(name = "employee")
public class EmployeeEntity {
private CompositeEmployeeKey id;
private String name;
private String lastName;
@Override
@EmbeddedId
public CompositeEmployeeKey getId() {
return id;
}
@Override
public void setId(CompositeEmployeeKey id) {
this.id = id;
}
.
.
.
public class CompositeEmployeeKey implements Serializable {
private String companyId;
private String employeeId;
Once the generation is complete, implement PersistenceEntity<ID>.java in the EmployeeEntity and pass the composite primary key object which is CompositeEmployeeKey in this case as the parameter ID.
import com.devonfw.module.basic.common.api.entity.PersistenceEntity;
@Entity
@Table(name = "employee")
public class EmployeeEntity implements PersistenceEntity<CompositeEmployeeKey> {
private CompositeEmployeeKey id;
private String name;
private String lastName;
Also, the modificationCounter methods needs to be implemented from the interface PersistenceEntity<ID>. The sample implementation of the modification counter can be referred below.
@Override
public int getModificationCounter() {
if (this.persistentEntity != null) {
// JPA implementations will update modification counter only after the transaction has been committed.
// Conversion will typically happen before and would result in the wrong (old) modification counter.
// Therefore we update the modification counter here (that has to be called before serialization takes
// place).
this.modificationCounter = this.persistentEntity.getModificationCounter();
}
return this.modificationCounter;
}
@Override
public void setModificationCounter(int version) {
this.modificationCounter = version;
}


US ConstitutionBy Ariel G. Arellano, Pedro Morales, and Ivan Rosales Flores
Articles
Amendments
Cited Sources
Article One
Congress, according to the elastic clause, has all the powers to make laws that it deems appropriate. Congress is comprised of two houses: The house of Representatives and the Senate. The two houses work together to make and pass legislation. Both positions require different sets of criteria. In order to make a law, both houses must agree upon it. Then, it reaches the president for which he has to agree on it. If he signs it, it becomes a law. If it is not signed, it goes back to congress, for which it has to receive ⅔’s of the votes in each house to then become a law. Congress has certain protections and powers that it can decide to use. It can tax, pay loans, get loans, call war, form army, admit states, etc. Congress also has the protections to not be arrested if they are in a meeting, for whichever reason.
Article Two
Creates the job of President, called the Executive. Responsible for enforcing the laws.
Section 1:
Establishes the office of the President and the Vice-President.
Both serve for four years.
 Must be born in the USA.
Their pay cannot change, up or down, as long as he is in office.
Section 2:
President leads the armed forces.
He has a Cabinet to help him, and can pardon criminals.
He makes treaties with other nations (2/3 of the Senate have to approve of the treaty).
Picks many of the judges and other members of the government.
Section 3:
President must give a yearly speech to the nation.
Give suggestions to Congress.
Meet with Ambassadors and other heads of state from other nations.
Ensure the laws of the United States are carried out.
Section 4:
Explains how to kick the president from office, called impeachment.
Article Three
Deals with the judicial branch. The Judicial branch are the law and court cases. This includes supreme court cases and other courts created by congress.
Section 1: The federal court system has to have one supreme court.
Includes chief justice and 8 other justices.
Congress can create and remove lower courts, there doesn’t have to be any if they don’t want them.
A judge can be in office until they die, are convicted, or impeached.
A judge's pay can be increased, but it cannot be decreased.
Section 2: Who gets power:
The supreme court can decide what cases they want to see.
The supreme court has the right to see any case if they would like to.
A defendant doesn’t have to get a jury if he or she does not want one.
Section 3: Treason
When you launch any type of attack against the United States and you are a citizen of the U.S..
AT least two witnesses to the act.
Or person can confess to treason.
Article Four
States’ responsibilities, process for creating new states, federal government promises to protect and defend the states.
Article Five
Making Amendments or Changes
1.Proposal
a. 2/3 of Congress (Senate and House) can vote for proposing a change.
b. 2/3 of State Legislatures can vote for a convention to propose a change.
2.Ratification
¾ of States must vote to ratify amendments(either state legislatures or special state convention).
Article Six
Constitution is the “Supreme law of the land”.
National government is supreme in conflicts over individual states.
State law cannot contradict national law.
“Supreme law of the land”
Article Seven
Ratification of the constitution occurs only when 9 of the 13 states agrees to the constitution.
One
Freedom of speech, press, religion, and petition in the United States.
Two
The right to bear arms.
Three
Soldiers should not have the right to quarter.
Four
In order to search someone, a warrant is required.
Five
A grand jury gives verdict for crimes that are serious. Citizens are not to be tried for the same crime twice.
Six
A trial that is quick and speedily is given to citizens that have committed a crime.
Seven
A trial is given to the citizen in a civil suits if the amount exceeds $20.
Eight
Very high bales, unfair fines, or punishment that can be correlated to torture is against the law.
Nine
Just because a right isn’t listed does not mean the right is protected.
Ten
All powers not given by the Constitution are reserved to the states or the local government.
Eleven
A member from another state or of a foreign country cannot sue a state from the U.S courts.
Twelve
Electors should put the person they want for president and vice president on their ballot.
Thirteen
Abolishes slavery and involuntary servitude.
Fourteen
States are not allowed to pass laws that deprive people of their unalienable rights: life, liberty, and property without the proper process of trial.
Fifteen
States cannot systematically prevent people of any race to vote.
Sixteen
Income tax
Seventeen
State legislatures can no longer vote for the senators. The people are to fulfill that duty.
Eighteen
Alcohol manufacturing, sale, or shipment is against the law.
Nineteen
Women suffrage
Twenty
Changes the inauguration of the president. It makes it on January rather than on March, which makes it earlier. This occurred because FDR was seeking to make changes during the Great Depression, but he had to wait so long till he was actually in office. Keep in mind, he was technically already president.
Twenty One
Repeal of the 18th amendment (prohibition repeal).
Twenty Two
No president is allowed to run for more than 2 terms. (technically the max is 10 years if the vice president takes over at the right time).
Twenty Three
Gives DC three electoral votes for elections
Twenty Four
No person should be denied to vote because of a failure to pay a poll tax or any other type of tax.
Twenty Five
Allows the vice president to become president after the resignation or death of the current president.
Twenty Six
18 year olds are allowed to vote
Twenty Seven
Changes in pay for congressional members shall be enforced in the next term.


X Factor contestant Ariel Burdett dies at the age of 38, friends say
X Factor 2008 contestant Ariel Burdett has died at the age of 38, it's reported
by Molly Pike, https://www.mirror.co.uk/authors/molly-pike/X Factor contestant Ariel Burdett has died at the age of 38, it's reported.
A friend says the singer, who appeared on the show in 2008, died earlier this month but a cause of death is yet to be revealed, according to the Daily Star Online.
Ariel, whose real name is Amy Burdett, had one of the most memorable auditions in the show's history.
As she arrived to present herself to the judges she ripped her label on the floor, saying she was a "human being, not a number".
Ariel also told Cheryl, who was an X Factor judge at the time, she was "stupid" after she got given four nos.
She sported bright blonde dreadlocks and dark black eye makeup in the infamous clip.
Ariel told them she was a "specialist and not a generalist" and worked as a "holistic vocal coach".
Her song was an "academic construction", she claimed.
After failing to make it through to the next round, she told the judges to "shove a bit of metal right up their a**".
She had changed her name to Arabella Starchild after her famous audition.
The friend also posted a picture of Ariel on social media, asking them to get in touch with her brother about funeral arrangements.
Tributes have poured in for Ariel on social media.
One wrote: "Ariel Burdett is gone. What a loss."
Another posted: ""I can't believe that she died... rest in peace, Ariel Burdett."


DATA
VISUALIZATIONS
PERFORMANCE
PREDICTION
Data Collection
Data Cleaning
Data Description
Creator: R.A. Fisher
Donor: Michael Marshall
This data is collected from https://archive.ics.uci.edu/ml/datasets/Iris
Number of Instances: 150
Missing Values: 0
Duplicate Values: 0
No significant data cleaning was required for this dataset
Title: Iris Plants Database
Attribute Information:


We aggregate bitcoin!
- synthesize user-centric solutions
- orchestrate clicks-and-mortar schemas
- expedite B2C e-markets
- benchmark distributed e-business
- transition extensible infrastructures
- envisioneer collaborative deliverables
- seize dynamic content
- deliver sticky action-items


These terms and conditions outline the rules and regulations for the use of Boop's website and web application, located at https://boopboop.app.
When you register an account on this application, you accept these terms and conditions. Do not continue to use Boop if you do not agree to take all the terms and conditions stated on this page.
The following terminology applies to these Terms and Conditions, Privacy Statement and Disclaimer Notice and all Agreements: "You" and "Your" refers to you, the person using this service and compliant to these terms and conditions. "Ourselves", "We", "Our" and "Us", refers to the Boop team, which is a "junior design" project team at the Georgia Institute of Technology.
We employ the use of cookies to remember that you are logged in between sessions. Most interactive websites use cookies to let us retrieve the user's details for each visit. You may choose to disable cookies in your web browser if you do not want to stay logged in.
The Boop software is copyright (c) 2021 Grace Rarer, Gunnar Andra-Thomas, Juan Caicedo, Porter Hunley, Sanjana Jampana, and Jiale Zheng, and is available as open-source software under the MIT software license.
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
 IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
You can find the source code for the Boop software at https://github.com/grarer/boop
Parts of this website offer an opportunity for users to create a profile, including “status messages” and “profile descriptions”.
Boop does not filter, edit, publish or review user-generated content prior to its presence on the website. User-generated content does not reflect the views and opinions of Boop, Its agents and/or affiliates. To the extent permitted by applicable laws, Boop shall not be liable for user-generated content or for any liability, damages or expenses caused and/or suffered as a result of any use of and/or posting of and/or appearance of the user-generated content on this website.
Boop reserves the right to monitor all user-generated content and to remove any user-generated content or user account at any time and for any reason.
You warrant and represent that:
You hereby grant Boop a non-exclusive license to use, reproduce, edit and authorize others to use, reproduce and edit the user-generated content of your Boop profile.
Without prior approval and written permission, you may not create frames around our Webpages that alter in any way the visual presentation or appearance of our Website.
We reserve the right to amend these terms and conditions and our privacy policy at any time.


-
Mocha
Coffee
photos/candles.jpg
-
Decaf
Coffee
photos/teacup.jpg
-
Raspberry Zinger
Tea
photos/teapot_white.jpg
-
Earl Grey
Tea
photos/teapot_bone.jpg
Single-Record Binding with XML Data Islands
This example demonstrates binding an XML data island to a set of HTML elements that can only
display one record at a time, and then using the built-in recordset navigation functions to move
among the records of data.
Product Name:
Product Type:


Hello! my name is:
Green Blob
Firstname
Lastname
Age
likes
Green
Blob
16
3
Like if you want to go out with me ;)


haleybees
portfolio
ceramics
+everything else
about
contact
"everything else"
portfolio
home
everything else portfolio
Dante's CNC Table
light pressure table
Colonial silkscreen
Collapse silkscreen
brazen bee scarf
brood hive scarf
bullet ant pendant
Ewan hinged cuff
Geometric Ring
Organic Earrings
Anthill Sculptural Ring
click to jump to top of page


Defines a single half edge on our graph
| m_pNext | Next half edge in edge loop |
| m_pPrev | Previous half edge in edge loop |
| m_pOpposite | Opposite half edge |
| m_pVertex | Vertex at head of edge |
| m_pFace | Face to the left of edge |
| m_smoothingGroup | Smoothing group this edge belongs to index - |
Returns the face this edge is a boundary of
Pointer to the current face
Returns the smoothing group this edge belongs to
ID of the smoothing group this edge belongs to


This project is a first attempt at creating a system for automatically keeping track of Glitch projects in Trello using the Glitch API and the Trello API. If you submit the name of one of your Glitch projects it will create a list of all of your Glitch projects, with the option to create a Trello Board for the project, with a color of your choice. It is written in CoffeeScript and you can view the source here. The boards for this proof of concept are created in the PatrickWeaverGlitchProjects Team on Trello.


Description:
Indirect call of a subroutine pointed to by the Z (16 bits) pointer register in the register file and the EIND register in the I/O space. This instruction allows for indirect calls to the entire program memory space. The stack pointer uses a post-decrement scheme during EICALL.
This instruction is not implemented for devices with 2 bytes PC, see ICALL. Refer to the device specific instruction set summary.
Operation:
PC(15:0) ← Z(15:0)
PC(21:16) ← EIND
Syntax: Operands: Program Counter: Stack:
EICALL None See Operation STACK ← PC + 1
SP -< SP - 3 (3 bytes, 22 bits)
16-bit Opcode:
|
1001 |
0101 |
0001 |
1001 |
Status Register (SREG) and Boolean Formula:
|
I |
T |
H |
S |
V |
N |
Z |
C |
|---|---|---|---|---|---|---|---|
|
- |
- |
- |
- |
- |
- |
- |
- |
Example:
ldi r16,$05 ; Set up EIND and Z pointer out EIND,r16 ldi 30, $00 ldi r31, $10 eicall ; Call to $051000
Words: 1 (2 bytes)
Cycles:
|
Cycles |
Cycles xmega | |
|---|---|---|
|
Only implemented in devices with 22-bit PC |
4 |
3 |


Having trouble seeing this email? View in your browser
With Louisiana’s ACT benchmarks slated to rise to 21, it’s more important than ever to make sure your students are getting the test-prep they need to earn college-ready scores.
We offer a number of ACT and WorkKeys prep courses featuring both in-person and online instruction.
Depending on the course you’re interested in, your students can receive either a half or full credit of instruction with a unique syllabus catered to their specific needs.
We are committed to helping every student reach college benchmarks!
Interested in learning more?
Phone:<PHONE_NUMBER>
Email: sca@masteryprep.com


ORDERS
399
+45% From previous month
INCOM
$18,628
+45% From previous month
VISITORS
23,456
+25% From previous month
CUSTOMERS
4,367
+25% From previous month
| Image | Product | Customer | Purchased On | Status | Tracking No# |
|---|---|---|---|---|---|
| iMac | Russell | 22/08/2016 | Paid | #98BC85SD84 | |
| iPhone | Carol | 15/07/2016 | Pending | #98SA3C9SC | |
| apple Watch | Austin Pena | 10/07/2016 | Paid | #98BC85SD84 | |
| mac Mouse | Randy | 22/04/2016 | Failed | #98SA3C9SC |
REVENUE
GROS REVENUE
9,362,74
60%
NET REVENUE
6,734,58
78%


--- layout: page title: "Java Concurrency in Practice" prev: None next: main.html book_path: books/brian-goetz-tim-peierls-joshua-bloch-joseph-bowbeer-david-holmes-doug-lea-java-concurrency-in-practice--_oeb/ --- {% include JB/setup %} {% raw %}
Java Concurrency in Practice
Table of Contents
Copyright
Advance Praise for Java Concurrency in Practice
Listings
Preface
Chapter 1. Introduction
Section 1.1. A (Very) Brief History of Concurrency
Section 1.2. Benefits of Threads
Section 1.3. Risks of Threads
Section 1.4. Threads are Everywhere
Part I: Fundamentals
Chapter 2. Thread Safety
Section 2.1. What is Thread Safety?
Section 2.2. Atomicity
Section 2.3. Locking
Section 2.4. Guarding State with Locks
Section 2.5. Liveness and Performance
Chapter 3. Sharing Objects
Section 3.1. Visibility
Section 3.2. Publication and Escape
Section 3.3. Thread Confinement
Section 3.4. Immutability
Section 3.5. Safe Publication
Chapter 4. Composing Objects
Section 4.1. Designing a Thread-safe Class
Section 4.2. Instance Confinement
Section 4.3. Delegating Thread Safety
Section 4.4. Adding Functionality to Existing Thread-safe Classes
Section 4.5. Documenting Synchronization Policies
Chapter 5. Building Blocks
Section 5.1. Synchronized Collections
Section 5.2. Concurrent Collections
Section 5.3. Blocking Queues and the Producer-consumer Pattern
Section 5.4. Blocking and Interruptible Methods
Section 5.5. Synchronizers
Section 5.6. Building an Efficient, Scalable Result Cache
Summary of Part I
Part II: Structuring Concurrent Applications
Chapter 6. Task Execution
Section 6.1. Executing Tasks in Threads
Section 6.2. The Executor Framework
Section 6.3. Finding Exploitable Parallelism
Summary
Chapter 7. Cancellation and Shutdown
Section 7.1. Task Cancellation
Section 7.2. Stopping a Thread-based Service
Section 7.3. Handling Abnormal Thread Termination
Section 7.4. JVM Shutdown
Summary
Chapter 8. Applying Thread Pools
Section 8.1. Implicit Couplings Between Tasks and Execution Policies
Section 8.2. Sizing Thread Pools
Section 8.3. Configuring ThreadPoolExecutor
Section 8.4. Extending ThreadPoolExecutor
Section 8.5. Parallelizing Recursive Algorithms
Summary
Chapter 9. GUI Applications
Section 9.1. Why are GUIs Single-threaded?
Section 9.2. Short-running GUI Tasks
Section 9.3. Long-running GUI Tasks
Section 9.4. Shared Data Models
Section 9.5. Other Forms of Single-threaded Subsystems
Summary
Part III: Liveness, Performance, and Testing
Chapter 10. Avoiding Liveness Hazards
Section 10.1. Deadlock
Section 10.2. Avoiding and Diagnosing Deadlocks
Section 10.3. Other Liveness Hazards
Summary
Chapter 11. Performance and Scalability
Section 11.1. Thinking about Performance
Section 11.2. Amdahl's Law
Section 11.3. Costs Introduced by Threads
Section 11.4. Reducing Lock Contention
Section 11.5. Example: Comparing Map Performance
Section 11.6. Reducing Context Switch Overhead
Summary
Chapter 12. Testing Concurrent Programs
Section 12.1. Testing for Correctness
Section 12.2. Testing for Performance
Section 12.3. Avoiding Performance Testing Pitfalls
Section 12.4. Complementary Testing Approaches
Summary
Part IV: Advanced Topics
Chapter 13. Explicit Locks
Section 13.1. Lock and ReentrantLock
Section 13.2. Performance Considerations
Section 13.3. Fairness
Section 13.4. Choosing Between Synchronized and ReentrantLock
Section 13.5. Read-write Locks
Summary
Chapter 14. Building Custom Synchronizers
Section 14.1. Managing State Dependence
Section 14.2. Using Condition Queues
Section 14.3. Explicit Condition Objects
Section 14.4. Anatomy of a Synchronizer
Section 14.5. AbstractQueuedSynchronizer
Section 14.6. AQS in Java.util.concurrent Synchronizer Classes
Summary
Chapter 15. Atomic Variables and Nonblocking Synchronization
Section 15.1. Disadvantages of Locking
Section 15.2. Hardware Support for Concurrency
Section 15.3. Atomic Variable Classes
Section 15.4. Nonblocking Algorithms
Summary
Chapter 16. The Java Memory Model
Section 16.1. What is a Memory Model, and Why would I Want One?
Section 16.2. Publication
Section 16.3. Initialization Safety
Summary
Appendix A. Annotations for Concurrency
Section A.1. Class Annotations
Section A.2. Field and Method Annotations
Bibliography
Index
SYMBOL
A
B
C
D
E
F
G
H
I
J
K
L
M
N
O
P
Q
R
S
T
U
V
W


From the time she was a teenager, Erika knew that she wanted to adopt a child someday. “Every kid needs a family,” she reasoned. Even after giving birth to three children, Erika found that the longing to adopt still hadn’t subsided, so she approached her husband, Barry, with the idea of adding a fourth child to their family. Barry wasn’t as certain. Adoption would mean years of paperwork followed by a lot of adjustments to their already full life.
One weekend they attended church as usual, unaware that the guest speaker would be highlighting the great need for families willing to adopt. He talked about God’s heart for orphans and encouraged people to open their hearts and homes to give these children a place to grow up surrounded by love. By the time they were in the car on the way home from church, Barry and Erika were on the same page at last, asking God to bring them a child that needed a home.
As a family, they determined that to meet a need, they should go to the place on earth with the greatest need. So they decided on Ethiopia. Ethiopia has a population of about 80 million, and because it has been hit so hard by the AIDS epidemic, there are about 5 million orphans.
Barry and Erika began talking and praying with their children about the little boy they were hoping to adopt. In their conversations they called him Daniel, imagining the little brother who was waiting for them halfway around the world. When they finally received their confirmation letter, their son’s picture and a name were included. His Ethiopian name was Hiyab (pronounced HEE-ab), one that none of them had even heard of before. “A lot of kids get renamed when they come home to the United States,” Erika said. But when they learned the story behind the name, they immediately knew: “There’s no way we can change that!”
Hiyab’s birth parents met as teenagers, both of them Ethiopian Orthodox Christians. They moved to the big city of Addis Ababa but split up. They reunited


{% extends "app/base.html" %} {% block content %}
This is a pretty good stock guys!
Tesla stock overpriced imo


CUSTOMIZE EXTENSION
CHOOSE NOTIFICATION DELAY
Check for donors every
1
2
3
4
5
10
15
20
25
30
minute(s).


Now You can close this window.
It can't close this tab by itself because it require "tabs" permission for chrome extensions and some of You have real problem with this :)


This styleguide provides the basics for maintaining consistent style with the printed playbook. Keep in mind that this guide is incomplete, so you will need to extend it to address the needs of your project.
| Grey | Red | Yellow |
| #C4C9C4 | #CD000C | #F0AA00 |
| Green | ||
| #00B76B | #81DAB4 | #C2EED9 |
| Blue | ||
| #00A4CC | #82D3E5 | #C2E9F2 |
If you need to generate alternate sizes, use the vector versions in the images folder.
The Playbook uses Whitney HTF as it's typeface. The font files are included in the type folder; see the sytleguide.css for use. Alternate weights may need to be considered for different screen size or resolution. Alternate weights and families are available if needed.
Body text: Used for normal runs of text. Weight, and leading can be adjusted as appropriate for screensize and line length. You'll notice in the printed book the chapter spreads use variations of these guidelines where the body text describing the principles is smaller and heavier for the the white-on-color text, and the header and sub-header are used as reduced size. All of this to say these guidelines are just that, guides, and not rules set in stone.
Alt-body text: Small-cap variant used for supplementary text in side bars or chapter outlines


WASHINGTON - Pope Francis' gleaming white Alitalia plane - colloquially known as "Shepherd One" - touched down at Joint Base Andrews Tuesday, beginning a historic six-day, three-city visit that will have political, diplomatic and spiritual ramifications.
Breaking from the usual protocol for a state visit, President Obama and Vice President Biden chose to greet the papal plane at the Air Force base outside Washington before Francis departed in a hatchback Fiat to begin his tightly scheduled, carefully choreographed and highly anticipated visit.
He has an ambitious schedule: The pontiff will visit the White House, meet with U.S. Catholic bishops and celebrate a new saint with a canonization Mass for the Spanish missionary priest Junipero Serra on Wednesday. On Thursday, he'll be the first pope to address a joint meeting of Congress, and on Friday he'll address the nations of the world at the opening of the United Nations General Assembly.
Source: http://www.usatoday.com/story/news/politics/2015/09/22/pope-land-amid-political-spiritual-expectations/72619804/


You don't have any activity, why not create something ?
Are you sure you want to delete "{{project.title}}"?


User interface for accessing the operating system's services.
(I got that from wikipedia)
Another simple way to put it is:
- A program that takes in user input and has the OS perform the tasks.
This is the most basic it can get, not used as much, but still used in someplaces.
Places I have seen it used before:
This is what most are familar with
Bourne again shell
- Very similar to shell with some more added features.
- Since it has been made freely available for everyone, it has become a standard that a lot of people use.
It is an "upgraded" version of bash, with some feature built in improvements, i.e. tab complete commands.
Here are some notable frameworks that make it easier to use:
This is similar to zsh, but a lot of the customization is already done for you.
There are a lot more but these are the more "popular" ones that I am aware of there is:
We will talk about how we can start using these shells or rather what kind of information we can get.
'#!/bin/sh'
What is it?
#!
shebang
hashbang
poundbang
hashpling
(I also pulled these from wikipedia)
#!
Basicly says which interpreter to use.
#!/bin/bash
#!/bin/sh
#!/bin/csh
#!/usr/bin/perl
#!/path/to/interpreter
When trying to run a script (./scriptname) you are usually unable to run it at first.
The reason being, you usually don't have permission to.
ls
CCLulu∴~/workspace/shell-basics⨕master⚡
⤕ ls
CONTRIBUTING.md Gruntfile.js LICENSE README.md bower.json css demo.html index.html js lib node_modules package-lock.json package.json plugin res
ls -la
CCLulu∴~/workspace/shell-basics⨕master⚡
⤕ ls -la
total 496
drwxr-xr-x 21 Cuahuc staff 672 Feb 5 13:24 .
drwxr-xr-x 44 Cuahuc staff 1408 Feb 5 09:44 ..
-rw-r--r--@ 1 Cuahuc staff 8196 Feb 5 13:08 .DS_Store
drwxr-xr-x 12 Cuahuc staff 384 Feb 5 13:09 .git
-rw-r--r-- 1 Cuahuc staff 142 Feb 5 07:48 .gitignore
-rw-r--r-- 1 Cuahuc staff 75 Feb 5 07:48 .travis.yml
-rw-r--r-- 1 Cuahuc staff 1062 Feb 5 07:48 CONTRIBUTING.md
-rw-r--r-- 1 Cuahuc staff 3749 Feb 5 07:48 Gruntfile.js
-rw-r--r-- 1 Cuahuc staff 1103 Feb 5 07:48 LICENSE
-rw-r--r-- 1 Cuahuc staff 226 Feb 5 08:27 README.md
-rw-r--r-- 1 Cuahuc staff 512 Feb 5 07:48 bower.json
drwxr-xr-x 6 Cuahuc staff 192 Feb 5 07:48 css
-rw-r--r-- 1 Cuahuc staff 16240 Feb 5 07:48 demo.html
-rw-r--r-- 1 Cuahuc staff 7828 Feb 5 13:24 index.html
drwxr-xr-x 4 Cuahuc staff 128 Feb 5 08:28 js
drwxr-xr-x 5 Cuahuc staff 160 Feb 5 07:48 lib
drwxr-xr-x 466 Cuahuc staff 14912 Feb 5 07:51 node_modules
-rw-r--r-- 1 Cuahuc staff 182915 Feb 5 07:51 package-lock.json
-rw-r--r-- 1 Cuahuc staff 1066 Feb 5 07:48 package.json
drwxr-xr-x 11 Cuahuc staff 352 Feb 5 07:48 plugin
drwxr-xr-x 4 Cuahuc staff 128 Feb 5 09:19 res
Why do this?
-rw-r--r-- 1 Cuahuc staff 7828 Feb 5 13:24 index.html
drwxr-xr-x 4 Cuahuc staff 128 Feb 5 08:28 js
Let's break it down
r w x
1 1 1 = 7
1 1 0 = 6
1 0 1 = 5
1 0 0 = 4
0 1 1 = 3
0 1 0 = 2
0 0 1 = 1
0 0 0 = 0
User Group World
rwx rwx rwx
r w x | r w x | r w x
1 1 1 | 1 1 1 | 1 1 1 = 777
1 1 1 | 1 0 1 | 1 0 1 = 755
1 1 1 | 1 0 0 | 1 0 0 = 744
-rw-r--r-- 1 Cuahuc staff 7828 Feb 5 13:24 index.html
drwxr-xr-x 4 Cuahuc staff 128 Feb 5 08:28 js
r w x | r w x | r w x
1 1 1 | 1 0 1 | 1 0 1 = 755
1 1 0 | 1 0 0 | 1 0 0 = 644
Changing permissions
A simple command to change your file's permission:
chmod 777 filename.sh
chmod 755 filename.sh
chmod 744 filename.sh
Great, but how do I run it from anywhere?
Put in the PATH!
Is the place where your OS looks for where to run the binary
echo $PATH
/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Users/localadmin/bin:/Users/cuahuctemocosorio/bin:/Users/cuahuctemocosorio/go/bin
Last bit, some keyboard short cuts.
ctrl + a // jump to the beginning of the line
ctrl + e // jump to the end of the line
ctrl + u // clear the current line
ctrl + w // clear one word behind the cursor
ctrl + l // clear the terminal screen
ctrl + n // same as up arrow
ctrl + p // same as down arrow
ctrl + f // move forward one character
ctrl + b // move back one character