This is the second part of my blog series on how to develop mobile apps with GWT, Cordova and Netbeans. The initial description can be found here.
In the first part we did create a basic MGWT project from a maven template and did run it in the web browser of our choise.
It did just display a grey divider line on the screen, similiar to this.
Now we wish to show some real content on the page. For this we need to mobify the main class of the application.
The main application class is defined in your <project>.gwt.xml file.
Look for the <entry-point> xml tag, this is where your application starts.
You can now open this java file and search for the start() method.
The simplest way to get our hello world is to modify the start() method to only show a button with hello world as caption.
So your start() method should look like this:
private void start() {
//set viewport and other settings for mobile
MGWT.applySettings(MGWTSettings.getAppSetting());
LayoutPanel mainPanel= new LayoutPanel();
mainPanel.setWidth("100%");
Button button = new Button("Hello world");
button.setWidth("100%");
mainPanel.add(button);
RootPanel.get().add(mainPanel);
}
Don't delete the onModuleLoad method, this one is required.
After a rebuild und run of the project, you should now see the "Hello world" button on your browser, similar to this printscreen.
Initial description
Part 1
In the next part we will now go to the magic, and put this in a android and windows phone app.
Monday, June 2, 2014
App development with GWT, Cordova and Netbeans Part 1
This is the first part of my blog series on how to develop mobile apps with GWT, Cordova and Netbeans. The initial description can be found here.
To develop with Netbeans, of course you need the Netbeans IDE.
I suggest downloading the latest version 8.0 from the official website and install it. Just make sure you take the "All" edition, which includes support for Java and HTML5.
When the IDE is installed, you should download and install the GWT plugin for netbeans. It can be downloaded directly from the netbenas plugins web page.
The plugin then requires the GWT environment. If not yet installed, download it from here (The GWT SDK is enough) and unpack it somewhere on your local disk.
After this your development environment is ready to start.
When netbeas is started you first create a new maven project target, select "Maven" and then "Project from Archtype"
Then enter the specified values below in the 4 text fields to generate a MGWT target:
Group-ID: com.googlecode.mgwt.archetypes
Artifact ID: mgwt-standard-archetype
Version: 1.0.8
Repository: http://www.m-gwt.com/m2/repo
Now you specify where to store your new project and your own "namespace", usually something like com.company and the project name.
After finishing you have the skeleton for the MGWT project ready. In the project name you see "Archtype generated mgwt app", with a right click on the project you can open the project dialog and put in a meaningfull project name.
So you are now ready to run the project.
Just right click on the project and select "Run"
It now asks you on which application server you with to run it, don't be worried, you won't need it for the final deployment. But for development purposes your code needs to be accessible via a http connection. So just select one of the installed application servers. (When you select "Remember Permanently" it won't aks you over and over again)
Netbeans now invokes the GWT compiler and trys to build your web application.
Unfortunaly the build will fail, complaining about a missing clientcode.xml
------------------------------------------------------------------------
BUILD FAILURE
------------------------------------------------------------------------
------------------------------------------------------------------------
Failed to execute goal org.apache.maven.plugins:maven-assembly-plugin:2.2-beta-5:single (assemble) on project mgwt1: Error reading assemblies: Error locating assembly descriptor: src/main/assembly/clientcode.xml
[1] [INFO] Searching for file location: C:\Develop\Sourceforge\mgwt1\src\main\assembly\clientcode.xml
[2] [INFO] File: C:\Develop\Sourceforge\mgwt1\src\main\assembly\clientcode.xml does not exist.
The clientcode.xml contains some informations on what should be packaged for the final app.
Just create the clientcode.xml in the folder src/main/assembly with this content:
<assembly>
<id>clientcode</id>
<includeBaseDirectory>false</includeBaseDirectory>
<formats>
<format>zip</format>
</formats>
<fileSets>
<fileSet>
<directory>target/${project.artifactId}-${project.version}</directory>
<includes>
<include>**/*.js</include>
<include>**/*.png</include>
<include>**/*.rpc</include>
<include>**/*.html</include>
<include>**/*.gif</include>
</includes>
<outputDirectory></outputDirectory>
</fileSet>
</fileSets>
</assembly>
Now you can run the project once more, and if your default browser is a webkit based browser you will see the screen similar to this:
If you instead receive a error message like :
ERROR: Possible problem with your *.gwt.xml module file.
The compile time user.agent value (safari) does not match the runtime user.agent value (gecko1_8). Expect more errors
then you have started your web app in another browser which is not based on webkit.
If you wish to continue using your belowed browser, then just change the compile option in the <project>.gwt.xml file. Just remove the line <set-property name="user.agent" value="safari" /> and re run your project.
This is the first step in building a GWT based mobile app with netbeans.
In the second step we will change the content of the start screen, you we see our belowed "Hello World" text.
To develop with Netbeans, of course you need the Netbeans IDE.
I suggest downloading the latest version 8.0 from the official website and install it. Just make sure you take the "All" edition, which includes support for Java and HTML5.
When the IDE is installed, you should download and install the GWT plugin for netbeans. It can be downloaded directly from the netbenas plugins web page.
The plugin then requires the GWT environment. If not yet installed, download it from here (The GWT SDK is enough) and unpack it somewhere on your local disk.
After this your development environment is ready to start.
When netbeas is started you first create a new maven project target, select "Maven" and then "Project from Archtype"
Group-ID: com.googlecode.mgwt.archetypes
Artifact ID: mgwt-standard-archetype
Version: 1.0.8
Repository: http://www.m-gwt.com/m2/repo
Now you specify where to store your new project and your own "namespace", usually something like com.company and the project name.
After finishing you have the skeleton for the MGWT project ready. In the project name you see "Archtype generated mgwt app", with a right click on the project you can open the project dialog and put in a meaningfull project name.
So you are now ready to run the project.
Just right click on the project and select "Run"
It now asks you on which application server you with to run it, don't be worried, you won't need it for the final deployment. But for development purposes your code needs to be accessible via a http connection. So just select one of the installed application servers. (When you select "Remember Permanently" it won't aks you over and over again)
Netbeans now invokes the GWT compiler and trys to build your web application.
Unfortunaly the build will fail, complaining about a missing clientcode.xml
------------------------------------------------------------------------
BUILD FAILURE
------------------------------------------------------------------------
------------------------------------------------------------------------
Failed to execute goal org.apache.maven.plugins:maven-assembly-plugin:2.2-beta-5:single (assemble) on project mgwt1: Error reading assemblies: Error locating assembly descriptor: src/main/assembly/clientcode.xml
[1] [INFO] Searching for file location: C:\Develop\Sourceforge\mgwt1\src\main\assembly\clientcode.xml
[2] [INFO] File: C:\Develop\Sourceforge\mgwt1\src\main\assembly\clientcode.xml does not exist.
The clientcode.xml contains some informations on what should be packaged for the final app.
Just create the clientcode.xml in the folder src/main/assembly with this content:
<assembly>
<id>clientcode</id>
<includeBaseDirectory>false</includeBaseDirectory>
<formats>
<format>zip</format>
</formats>
<fileSets>
<fileSet>
<directory>target/${project.artifactId}-${project.version}</directory>
<includes>
<include>**/*.js</include>
<include>**/*.png</include>
<include>**/*.rpc</include>
<include>**/*.html</include>
<include>**/*.gif</include>
</includes>
<outputDirectory></outputDirectory>
</fileSet>
</fileSets>
</assembly>
Now you can run the project once more, and if your default browser is a webkit based browser you will see the screen similar to this:
If you instead receive a error message like :
ERROR: Possible problem with your *.gwt.xml module file.
The compile time user.agent value (safari) does not match the runtime user.agent value (gecko1_8). Expect more errors
then you have started your web app in another browser which is not based on webkit.
If you wish to continue using your belowed browser, then just change the compile option in the <project>.gwt.xml file. Just remove the line <set-property name="user.agent" value="safari" /> and re run your project.
This is the first step in building a GWT based mobile app with netbeans.
In the second step we will change the content of the start screen, you we see our belowed "Hello World" text.
Quickstart mobile app development with GWT, Cordova and Netbeans
Mobile app development is a fast moving target. You have many options on how to develop mobile apps.
The most sophisticated way is to write native apps for each platform...
Of course you will need to master the different languages and development environments. And since you will have to develop the same functionality for several platforms, you will code it multiple times in different languages.
Happy you if you find a customer willing to pay for it.
If you wish to use the "write once run anywhere" system, then you will be landing on web apps. Fortunally today mobile devices are in most cases fast enough to run you web app without feeling slugish. So you basically can write a html 5 website and make it available as a app.
For this you can use the phonegap / cordova framework.
If you need access to some native parts of the mobile device (Sensors, camera etc.) then you can use many of the available plugins which then allows you to access these hardware specific features.
Even better, you can use the adobe build service to build the whole application from your html/javascript sources.
If you come from the java world, then writing javascript isn't that sexy, you could then use GWT to write your web app in java and let the compiler generate java script stuff from it.
The performance of the generated code is very good, you will have a hard time to make such optimized java script code.
In this blog post serie I will guide you through the process of creating a project in netbeans, which you can then use to build your mobile application from your familiar ide.
Such apps are able to run under iOS, Android and Windows Phone. Of course platform specific features will only be available on the specific platform.
So let's start with Part 1 of the tutorial
Step 2 - Modify content
Step 3 - Build native apps
The most sophisticated way is to write native apps for each platform...
Of course you will need to master the different languages and development environments. And since you will have to develop the same functionality for several platforms, you will code it multiple times in different languages.
Happy you if you find a customer willing to pay for it.
If you wish to use the "write once run anywhere" system, then you will be landing on web apps. Fortunally today mobile devices are in most cases fast enough to run you web app without feeling slugish. So you basically can write a html 5 website and make it available as a app.
For this you can use the phonegap / cordova framework.
If you need access to some native parts of the mobile device (Sensors, camera etc.) then you can use many of the available plugins which then allows you to access these hardware specific features.
Even better, you can use the adobe build service to build the whole application from your html/javascript sources.
If you come from the java world, then writing javascript isn't that sexy, you could then use GWT to write your web app in java and let the compiler generate java script stuff from it.
The performance of the generated code is very good, you will have a hard time to make such optimized java script code.
In this blog post serie I will guide you through the process of creating a project in netbeans, which you can then use to build your mobile application from your familiar ide.
Such apps are able to run under iOS, Android and Windows Phone. Of course platform specific features will only be available on the specific platform.
So let's start with Part 1 of the tutorial
Step 2 - Modify content
Step 3 - Build native apps
Friday, February 21, 2014
Installing the DHCP Role on Windows 2012 R2 Server
Unable to install DHCP server role on Windows 2012 Server Essential.
When you try to install the DHCP Role on a windows 2012 R2 server, then the role installation might just stop with the error "0x800f0922".
Searching for this error message shows a astonishing amount of questions about this, so you are in good company.
Some solutions tell you to disable automatic web proxy detection, or disconnect the network cable from the server during the installation of the DHCP role.
When you wish to know what happens, then look in the %SYSTEMROOT%\System32\DHCP for some logfiles.
In our case the newly installing dhcp server detects a already running dhcp server in the network and so refuses to install a local DHCP server.
So it's clear why disconnecting the network cable solves the installation problem, the other dhcp server is then no longer visible.
But why, why is preventing the installation of the dhcp server role?
And why, why is there such a cryptic nonsense error message instead of a real error message?
When you try to install the DHCP Role on a windows 2012 R2 server, then the role installation might just stop with the error "0x800f0922".
Searching for this error message shows a astonishing amount of questions about this, so you are in good company.
Some solutions tell you to disable automatic web proxy detection, or disconnect the network cable from the server during the installation of the DHCP role.
When you wish to know what happens, then look in the %SYSTEMROOT%\System32\DHCP for some logfiles.
In our case the newly installing dhcp server detects a already running dhcp server in the network and so refuses to install a local DHCP server.
So it's clear why disconnecting the network cable solves the installation problem, the other dhcp server is then no longer visible.
But why, why is preventing the installation of the dhcp server role?
And why, why is there such a cryptic nonsense error message instead of a real error message?
Labels:
dhcp,
setup,
windows 2012R2,
windows 2012r2 essentials
Wednesday, February 19, 2014
Adding a Windows 2012 R2 Essential Server to a existing domain
Adding a new Windows 2012 R2 Essentials server to a existing domain is a supported scenario by microsoft.
The new server will then be the primary server for all the ADS roles.
Unfortunally this does not mean it will just work out of the box.
The basic steps for this are:
- Make the basic installtion of the windows server
- Don't follow the wizard after installation, just cancel it
- Important: Set the server name you wish to use now, you won't be able to change it later on
- Install the Active Directory Services on the new server
- Add the new server as a additional ADS server in the existing domain
- Let the wizard finish the essentials configuration
The details can be found on the microsoft product site.
Unfortunally the wizard won't finish, but rather say: Error occured and nothing is logged.
The post-config wizard won't let you configure the Essentials Experience role because it's unable to start the 'Windows Server Essentials Management Service' system service. This service is configured to run under the <domain>\ServerAdmin$ account. This account must have 'Log on as a service' rights.
The new server will then be the primary server for all the ADS roles.
Unfortunally this does not mean it will just work out of the box.
The basic steps for this are:
- Make the basic installtion of the windows server
- Don't follow the wizard after installation, just cancel it
- Important: Set the server name you wish to use now, you won't be able to change it later on
- Install the Active Directory Services on the new server
- Add the new server as a additional ADS server in the existing domain
- Let the wizard finish the essentials configuration
The details can be found on the microsoft product site.
Unfortunally the wizard won't finish, but rather say: Error occured and nothing is logged.
The post-config wizard won't let you configure the Essentials Experience role because it's unable to start the 'Windows Server Essentials Management Service' system service. This service is configured to run under the <domain>\ServerAdmin$ account. This account must have 'Log on as a service' rights.
- Go to Group Policy Management
- Edit your policy, such as the 'Default Domain Controllers Policy'
- Go to Computer Configuration \ Windows Settings \ Security Settings \ Local Policies \ User Rights Assignment
- Edit 'Log on as a service' and add 2 accounts: <domain>\ServerAdmin$ and <domain>\MediaAdmin$
Labels:
ads,
windows,
windows 2012R2,
windows 2012r2 essentials
Thursday, January 23, 2014
Vaadin JPAContainer, Filterable table and related entities
In the web 2.0 framework Vaadin you have containers which provide data to be displayed in your application.
These containers are very flexible and can for example be a databasebackend, a JPA system or your own implementation.
In my past post I showed you how to implement filtering for related fields.
Vaadin also provides many data aware components, for example a table component.
The table component is very sophisticated and allows displaying huge amounts of data in the webbrowser. The table has a lazy loading system, so as only the visible parts of a table are retrieved from the backend and sent to the webbrowser.
There also exists a addon component which has built in filter and sort support.
When using the table with jpa container, then you have to use several tricks to allow filtering on related fields.
You don't have to store the property, it's enough for the JPA container when you have a getXXX() method.
That way it displays the additional properties in the table. You could also use this way to show calculated related fields in the table.
This could look like this:
public String getProjectInfos()
{
return projectNr+" - "+name;
}
When you now display these in the table, you can also filter on that field.
But then, you will get a error message, telling you that the sql select did not find the field for the where condition.
contentTable.setFilterGenerator(new MyFilterGenerator());
The filter generator has different methods, when you don't want to override them, you can just return NULL and then the default behaviour is done.
For us the interesting method is the generateFilter() method.
Here you can implement your own conditions.
If you for example wish to filter with the LIKE statement, then you can do it this way:
@Override
public Container.Filter generateFilter(Object propertyId, Object value)
{
if ("contract".equals(propertyId))
{
if (value != null && value instanceof String)
{
return new Like("contractID", value.toString()+"%");
}
}
return null;
}
To now filter on a related table, you can use the IN condition, which then builds the correct sql statements.
@Override
public Container.Filter generateFilter(Object propertyId, Object value)
{
if ("contracts".equals(propertyId))
{
if (value != null && value instanceof String)
{
String lsNr= (String) value;
EntityManager em= ((MyVaadinUI)UI.getCurrent()).getEntityManager();
TypedQuery<Shippings> tq= em.createNamedQuery("Shippings.findByLikeProjectNr", Shippings.class);
tq.setParameter("projectNr", lsNr+"%");
List<Shippings> rs= tq.getResultList();
if (rs.isEmpty())
{
return new IsNull("shipping");
}
else
{
if (rs.size() > 2000)
{
Notification.show("To many entries", "\n\nMake more restrictions", Notification.Type.WARNING_MESSAGE);
return new IsNull("shipping");
}
else
{
return new In("shipping", rs);
}
}
}
}
return null;
}
So when the property contracts has some value, we filter the contracts by projectNr and use the resulting result set to specify as the IN criteria.
If you are still with me, then you probably have a compiler error when you try this code.
The reason is, that the default JPAContainer has no implementation of the IN criteria.
Unfortunally the design of the JPAContainer does not allow to expand the capabilities in that area.
Fortunally there exists a fork of the JPAContainer which just provides the required IN() clause.
You can download the sources and add them to your project.
The source can be found here: https://github.com/lelmarir/jpacontainer
You can learn how to show related / nested properties in this post.
These containers are very flexible and can for example be a databasebackend, a JPA system or your own implementation.
In my past post I showed you how to implement filtering for related fields.
Vaadin also provides many data aware components, for example a table component.
The table component is very sophisticated and allows displaying huge amounts of data in the webbrowser. The table has a lazy loading system, so as only the visible parts of a table are retrieved from the backend and sent to the webbrowser.
There also exists a addon component which has built in filter and sort support.
When using the table with jpa container, then you have to use several tricks to allow filtering on related fields.
The first trick is to display the related fields in the table
For this the simplest way is to add these related fields to the main entity you display.You don't have to store the property, it's enough for the JPA container when you have a getXXX() method.
That way it displays the additional properties in the table. You could also use this way to show calculated related fields in the table.
This could look like this:
public String getProjectInfos()
{
return projectNr+" - "+name;
}
When you now display these in the table, you can also filter on that field.
But then, you will get a error message, telling you that the sql select did not find the field for the where condition.
For this to work, you have to use the second trick
You can build your own FilterGenerator which then builds the correct criterias for your tables and relations.contentTable.setFilterGenerator(new MyFilterGenerator());
The filter generator has different methods, when you don't want to override them, you can just return NULL and then the default behaviour is done.
For us the interesting method is the generateFilter() method.
Here you can implement your own conditions.
If you for example wish to filter with the LIKE statement, then you can do it this way:
@Override
public Container.Filter generateFilter(Object propertyId, Object value)
{
if ("contract".equals(propertyId))
{
if (value != null && value instanceof String)
{
return new Like("contractID", value.toString()+"%");
}
}
return null;
}
To now filter on a related table, you can use the IN condition, which then builds the correct sql statements.
@Override
public Container.Filter generateFilter(Object propertyId, Object value)
{
if ("contracts".equals(propertyId))
{
if (value != null && value instanceof String)
{
String lsNr= (String) value;
EntityManager em= ((MyVaadinUI)UI.getCurrent()).getEntityManager();
TypedQuery<Shippings> tq= em.createNamedQuery("Shippings.findByLikeProjectNr", Shippings.class);
tq.setParameter("projectNr", lsNr+"%");
List<Shippings> rs= tq.getResultList();
if (rs.isEmpty())
{
return new IsNull("shipping");
}
else
{
if (rs.size() > 2000)
{
Notification.show("To many entries", "\n\nMake more restrictions", Notification.Type.WARNING_MESSAGE);
return new IsNull("shipping");
}
else
{
return new In("shipping", rs);
}
}
}
}
return null;
}
So when the property contracts has some value, we filter the contracts by projectNr and use the resulting result set to specify as the IN criteria.
If you are still with me, then you probably have a compiler error when you try this code.
The reason is, that the default JPAContainer has no implementation of the IN criteria.
Unfortunally the design of the JPAContainer does not allow to expand the capabilities in that area.
Fortunally there exists a fork of the JPAContainer which just provides the required IN() clause.
You can download the sources and add them to your project.
The source can be found here: https://github.com/lelmarir/jpacontainer
You can learn how to show related / nested properties in this post.
Labels:
container,
filteringtable,
java,
jpa,
jpacontainer,
vaadin
Run linux commands via job queue
Often we have build long running jobs under linux which then call other shell scripts when they are finished.
Sometimes it would be possible to run such tasks partially concurrently, but for this we need some sort of job queue for the linux shell.
Unfortunally the cron/crontab does not allow such dependencies.
The simplest solution is to install the task spooler from this site.
You should however first look if your distribution has a binary package for it.
In debian you can install it via:
apt-get install task-spooler
After this, you can just put new jobs in the queue via the ts command.
Please note that in debian the command is named tsp to prevent name conflicts with the moreutils package.
When you just type ts(p) the system shows you all running/pending/completed tasks.
To put a new job in the queue you just type this:
ts(p) /home/user/mytask.sh
The job is then startet as soon as possible.
Per default the task spooler does start one task and waits until it is finished.
When the first task is finished it executes the next one from the queue and so on, until the queue is empty.
You can tell the task spooler to run multiple tasks concurrently,
you just set the maximum number of allowed concurrent executions with this command:
ts(p) -S 2
This would allow the task spooler to run up to two tasks concurrently.
You can also set priority on tasks, remove them from the queue an so on.
Look at the man page for more details.
As of 0.7.3 the man page does not list all options, to see all available options, use the -h option.
The output of the jost is per default stored in files in the /tmp folder.
You can view them, or use ts(p) to send them via email to some destination.
Sometimes it would be possible to run such tasks partially concurrently, but for this we need some sort of job queue for the linux shell.
Unfortunally the cron/crontab does not allow such dependencies.
The simplest solution is to install the task spooler from this site.
You should however first look if your distribution has a binary package for it.
In debian you can install it via:
apt-get install task-spooler
After this, you can just put new jobs in the queue via the ts command.
Please note that in debian the command is named tsp to prevent name conflicts with the moreutils package.
When you just type ts(p) the system shows you all running/pending/completed tasks.
To put a new job in the queue you just type this:
ts(p) /home/user/mytask.sh
The job is then startet as soon as possible.
Per default the task spooler does start one task and waits until it is finished.
When the first task is finished it executes the next one from the queue and so on, until the queue is empty.
You can tell the task spooler to run multiple tasks concurrently,
you just set the maximum number of allowed concurrent executions with this command:
ts(p) -S 2
This would allow the task spooler to run up to two tasks concurrently.
You can also set priority on tasks, remove them from the queue an so on.
Look at the man page for more details.
As of 0.7.3 the man page does not list all options, to see all available options, use the -h option.
The output of the jost is per default stored in files in the /tmp folder.
You can view them, or use ts(p) to send them via email to some destination.
Subscribe to:
Posts (Atom)