Tuesday, January 4, 2022

How to open the Dicom Image in Linux

This is a short tutorial on how we can open and view the Dicom images in Linux operating system.

Here, we will install weasis desktop application to view the Dicom images.

Installation

Download the desired weasis installer compatible with your operating system from weasis website. 

For Linux, download the .deb installer. Go to the download folder and open the terminal and execute the .deb file


sudo dpkg -i weasis_3.8.0-1_amd64.deb

Here, weasis_3.8.0-1_amd64.deb is the downloaded file, you can use your own downloaded .deb file.

Now, you are good to go to open the Dicom images. Go to the sample image and select the image and right-click, you can see open with weasis option, select and view the image. Or simply double click on the image which will open the installed weasis application to view the Dicom image.




Key Features
  • Display all kinds of DICOM files (including multi-frame, enhanced, MPEG-2, MPEG-4, MIME Encapsulation, SR, PR, KOS, AU, RT and ECG)
  • Image manipulation (pan, zoom, windowing, presets, rotation, flip, scroll, crosshair, filtering...)
  • Viewer for common image formats (TIFF, BMP, GIF, JPEG, PNG, RAS, HDR, and PNM)
  • Layouts for comparing series or studies
  • Advanced series synchronization options
  • Display Presentation States (GSPS) and Key Object Selection
  • Create key images (Key Object Selection object) by selection
  • Support of Modality LUTs, VOI LUTs, and Presentation LUTs (even non-linear) 
  • Support of several screens with different calibration, support of HiDPI (High Dots Per Inch) monitors, full-screen mode
  • Multiplanar reconstructions and Maximum Intensity Projection
  • Display Structured Reports
  • Display and search into all DICOM attributes
  • Display cross-lines Measurement and annotation tools
  • Region statistics of pixels (Min, Max, Mean, StDev, Skewness, Kurtosis, Entropy)
  • Histogram of modality values 
  • SUV measurement 
  • Save measurements and annotations in DICOM PR or XML file
  • Import CD/DVD and local DICOM files 
  • Export DICOM with several options (DICOMDIR, ZIP, ISO image file with Weasis, TIFF, JPEG, PNG...)
  • Magnifier glass Native and DICOM printing 
  • Read DICOM image containing float or double data (Parametric Map)
  • DICOM ECG Viewer
Share:

Saturday, December 18, 2021

How to change Grails App server port in application.yml

This is a quick tutorial on how to set server port while running grails application. By default, grails will use the embedded tomcat server running on port 8080.

Sometimes if another process is using port 8080 then we might get a port address already in use error.

So, what we will do is to change the default port in the config. In grails 3.x version we can set up the custom port inside application.yml file.

Inside application.yml file lets add the following config setup to override the default port 8080.
server:
    port : "8090"
Now if we run the application, it will run on port 8090. 

If we want to configure the setup within the environment then we can do as below:
environments:
    development:
        server:
            port : "8090"
This will set the server port only for the development environment. Re-run the application.
Share:

Thursday, December 9, 2021

How to resolve port already in use or kill the running process

 On Linux:


step1: if the process is running at port 3000 then, firstly we have to kill this process for this open your terminal and type

lsof -w -n -i tcp:3000

which shows all the list of open file which is running at port 3000. Here, lsof stands for ls = list and of = opened file. You can see list with pid number.


step2: type sudo kill -9 6911 where 6911 is pid number. Here 9 has its own meaning which is defined as kill command "SIGKILL" you can see this by typing in the terminal as kill -l . You can use -SIGKILL instead of -9.


On Windows:

Open and run command prompt as administrator and type the following command:
   
   netstat -ano | findstr :8080

This command will find and list the process that uses this port 8080.

Now, we need to kill the process, for this use following command:

   taskkill /pid 5884 /f

Where 5884 is the PID number. Use the process PID number obtained previously.
Share:

Sunday, November 21, 2021

Error occurred running Grails CLI: No profile found for name [web]. (Use --stacktrace to see the full trace)

In grails application, the error mentioned below might occur.

 

Error |
Error occurred running Grails CLI: No profile found for name [web]. (Use --stacktrace to see the full trace)

Process finished with exit code 1
This might be of different reason. Let's try to fix it by deleting the build folder under the application and re-run the application. 

This might work in most cases if this doesn't help then try to clean the app. 

If you are using the command line then type the following command to clean the application.
grails clean
if you are using the IntelliJ idea then Ctr+Alt+G opens the command window and use the following command.
clean
Now, re-run the app.
Share:

How to configure multiple database in Grails application

In this tutorial, we are going to learn how to configure multiple databases in the grails 3.x application. This is necessary when you are dealing with multiple databases from the same application especially when dealing with an existing remote database. We are using different MySql databases for testing.

Let's create three MySql databases called db_default, db_one, db_two. Let's look into the application.yml file to configure the different databases and we will do it for the development environment, in other environments, the procedure will be the same.


environments:
    development:
        dataSource:
            dbCreate: update
            url: jdbc:mysql://localhost:3306/db_default
            driverClassName: com.mysql.jdbc.Driver
            dialect: org.hibernate.dialect.MySQL5InnoDBDialect
            username: root
            password: root
Here, we are setting the default database as db_default. So for this database, all the gorm queries will be the same as in a normal application.

Now, let's set up for other two databases.
        dataSources:
            first:
                dialect: org.hibernate.dialect.MySQLInnoDBDialect
                driverClassName: com.mysql.jdbc.Driver
                username: root
                password: root
                url: jdbc:mysql://localhost:3306/db_one
                dbCreate: update
            second:
                dialect: org.hibernate.dialect.MySQLInnoDBDialect
                driverClassName: com.mysql.jdbc.Driver
                username: root
                password: root
                url: jdbc:mysql://localhost:3306/db_two
                dbCreate: update

For more than two, we need to define the databases by defining dataSources and giving the corresponding names. Here the custom name is whatever name you want. We are giving the name first for db_one and second for db_two.

The overall implementation for application.yml file looks as below:
environments:
    development:
        dataSource:
            dbCreate: update
            url: jdbc:mysql://localhost:3306/db_default
            driverClassName: com.mysql.jdbc.Driver
            dialect: org.hibernate.dialect.MySQL5InnoDBDialect
            username: root
            password: root
        dataSources:
            first:
                dialect: org.hibernate.dialect.MySQLInnoDBDialect
                driverClassName: com.mysql.jdbc.Driver
                username: root
                password: root
                url: jdbc:mysql://localhost:3306/db_one
                dbCreate: update
            second:
                dialect: org.hibernate.dialect.MySQLInnoDBDialect
                driverClassName: com.mysql.jdbc.Driver
                username: root
                password: root
                url: jdbc:mysql://localhost:3306/db_two
                dbCreate: update
Now, how we can use the domain classes for the specific databases. Let's create a simple domain class called Book.groovy.
class Book {
    String title
    
    static mapping = {
        datasource 'first' 
    }
}
In the above example, the Book table is mapped to the db_one database so all operations regarding this will be in db_one database. Similarly, we can map the second database as well. We can map the single domain to multiple databases as below:
class Book {
    String title
    
    static mapping = {
        datasources([ConnectionSource.DEFAULT, 'first', 'second'])
    }
}
In the above example, the Book domain will be available in all the databases.

Now, let's look into how we can query for the specific database.

The first DataSource specified is the default when not using an explicit namespace, so in this case, the default one is used. But you can call GORM methods on the 'first' or 'second' DataSource with the DataSource name, for example:
def book = Book.first.get(1) // this will get from db_one
book.first.save() //this will save in db_one
def book = Book.second.get(1) // this will get from db_two
book.second.save() // this will save in db_two
def book = Book.get(1) // this will get from db_default
book.save() // this will save in db_default

We can use groovy native SQL as well. Let's look at the example. 
import grails.transaction.Transactional
import groovy.sql.Sql
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.beans.factory.annotation.Qualifier

import javax.sql.DataSource

@Transactional
class DbOneService {

    @Autowired
    @Qualifier('dataSource_first')
    DataSource dataSource

    def test() {
        def sql = new Sql(dataSource)
        def rows = sql.rows("select * from....")
        println "rows: "+rows
    }
}
Here, we are creating the DbOneService which is annotated with Qualifier where the db_one database name is configured as dataSource_first. This will provide the db_one database connection to do DB operation. You can simply execute the native SQL command as shown above. Similarly, we can do the same for the second database called db_two.
import grails.transaction.Transactional
import groovy.sql.Sql
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.beans.factory.annotation.Qualifier

import javax.sql.DataSource

@Transactional
class DbTwoService {

    @Autowired
    @Qualifier('dataSource_second')
    DataSource dataSource

    def test() {
        def sql = new Sql(dataSource)
        def rows = sql.rows("select * from....")
        println "rows: "+rows
    }
}
This way, we can deal with multiple databases.
Share:

Saturday, November 20, 2021

How to convert Matlab functions into c or c++ code

In this tutorial, we are going to learn how we can convert the Matlab function into the c or c++ code. Note that the existing Matlab function needs to have c/c++ code generation extended capabilities.

Let's look into the sample Matlab scripts.

codegen.m

function y = codegen(I1)
 %#codegen
 y = typecast(I1, 'double');
Here, we are going to generate c code for function typecast of Matlab as given here. You can see the function does have the c/c++ code generation capabilities.

The first thing to do is add %#codegen as shown above. Open the file script on the editor and go to the APPS tab on the Matlab editor and you can find the MATLAB Coder option. Click on it.



Once you click on the MATLAB Coder option you can see the screen as below:



Select the script file created i.e codegen.m and the below screen will pop up and click the Next button for further steps.



Now, click on the link as shown below to add the input i.e I1 in our case which is defined in the function.



Now, lets define the input data.




Once click on the next button you can see the screen to check the issue, so you either check the issue or remove it by clicking on the screen outside of it. And click next to generate the code.
Click on generate button to generate the code. After build success, you can see the generated code as below:



This is a sample example for code generation. You can use the same methodologies for other Matlab inbuild functions to generate code in c/c++.
Share:

Wednesday, November 17, 2021

How to Compress(Zip) and Decompress(Unzip) byte array in Java

In this tutorial, we are going to compress and decompress the bytes array. The process may be required when serializing data as a binary file especially when the bytes array has non-unique data.

Let's create the method that compresses the bytes array.


import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.zip.DeflaterOutputStream;
public static byte[] compress(byte[] bytes) throws IOException {
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        DeflaterOutputStream deflaterOutputStream = new DeflaterOutputStream(byteArrayOutputStream);
        deflaterOutputStream.write(bytes);
        deflaterOutputStream.close();
        byte[] compressedBytes = byteArrayOutputStream.toByteArray();
        byteArrayOutputStream.close();
        return compressedBytes;
    }

This method will compress the bytes array. If this results in no reduction in length then the data might be unique or tend to be unique. If the data is truly unique random values then the compression might produce the greater length as well. Compression always has overhead to allow for future decompression.

Now, let's create a method that will decompress or unzip the underlying compressed data. 
import java.util.zip.InflaterInputStream;
import java.io.ByteArrayInputStream;
public static byte[] decompress(byte[] bytes) throws IOException {
        ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);
        InflaterInputStream inflaterInputStream = new InflaterInputStream(byteArrayInputStream);
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        int read;
        while ((read = inflaterInputStream.read()) != -1) {
            byteArrayOutputStream.write(read);
        }
        inflaterInputStream.close();
        byteArrayInputStream.close();
        byteArrayOutputStream.close();
        return byteArrayOutputStream.toByteArray();
    }
Let's create a test example to run these methods.

    public static void main(String[] args) {
        byte[] b = new byte[10000]; // bytes data with 0 values
        System.out.println("Initial Data Size : "+ b.length);
        try {
            byte[] compressedBytes = compress(b);
            System.out.println("Compressed Data Size : "+ compressedBytes.length);
            byte[] decompressedBytes = decompress(compressedBytes);
            System.out.println("Decompressed Data Size: "+ decompressedBytes.length);
        } catch (IOException e) {
            System.out.println("Error while zipping due to : "+e.getMessage());
        }
    }
Output:
Initial Data Size : 10000
Compressed Data Size : 33
Decompressed Data Size: 10000
There is an options to add different algorithm while doing compression using Deflater class as below
import java.util.zip.Deflater;
public static byte[] compress(byte[] bytes) throws IOException {
        Deflater deflater = new Deflater(Deflater.HUFFMAN_ONLY);
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        DeflaterOutputStream deflaterOutputStream = new DeflaterOutputStream(byteArrayOutputStream, deflater);
        deflaterOutputStream.write(bytes);
        deflaterOutputStream.close();
        byte[] compressedBytes = byteArrayOutputStream.toByteArray();
        byteArrayOutputStream.close();
        return compressedBytes;
    }
Here is overall code implementation:

Zip.java

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.zip.DeflaterOutputStream;
import java.util.zip.InflaterInputStream;
import java.io.ByteArrayInputStream;

public class Zip {

    public static void main(String[] args) {
        byte[] b = new byte[10000]; // bytes data with 0 values
        System.out.println("Initial Data Size : " + b.length);
        try {
            byte[] compressedBytes = compress(b);
            System.out.println("Compressed Data Size : " + compressedBytes.length);
            byte[] decompressedBytes = decompress(compressedBytes);
            System.out.println("Decompressed Data Size: " + decompressedBytes.length);
        } catch (IOException e) {
            System.out.println("Error while zipping due to : " + e.getMessage());
        }
    }

    public static byte[] compress(byte[] bytes) throws IOException {
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        DeflaterOutputStream deflaterOutputStream = new DeflaterOutputStream(byteArrayOutputStream);
        deflaterOutputStream.write(bytes);
        deflaterOutputStream.close();
        byte[] compressedBytes = byteArrayOutputStream.toByteArray();
        byteArrayOutputStream.close();
        return compressedBytes;
    }

    public static byte[] decompress(byte[] bytes) throws IOException {
        ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);
        InflaterInputStream inflaterInputStream = new InflaterInputStream(byteArrayInputStream);
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        int read;
        while ((read = inflaterInputStream.read()) != -1) {
            byteArrayOutputStream.write(read);
        }
        inflaterInputStream.close();
        byteArrayInputStream.close();
        byteArrayOutputStream.close();
        return byteArrayOutputStream.toByteArray();
    }
}
Share:

Tuesday, August 24, 2021

Format Date Time and Set Time Zone in Java

This is a quick tutorial on how to format the java Date in a format like "yyyy-MM-dd HH:mm:ss"  and also set the time zone for the date provided.

I would like to recommend always set the time in UTC while saving it in the database and also for the current date. Latter we can manipulate this UTC time to whatever timezone is required.

Now, let's see how we can format date time and also set the time zone in order to display to the user. Let's look at the example.

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;

public class DateUtils {
    public static void main(String[] args) {
        String dateFormat = "yyyy-MM-dd HH:mm:ss";
        String timeZone = "Asia/Jerusalem";
        Date date = new Date(); // current server time
        String formattedDate = formatDate(date, dateFormat, timeZone);
        System.out.println(formattedDate);
    }

    public static String formatDate(Date date, String dateFormat, String timeZone) {
        if (date == null) return ""; // or simply throw Exception
        DateFormat simpleDateFormat = new SimpleDateFormat(dateFormat);
         if (timeZone != null)
            simpleDateFormat.setTimeZone(TimeZone.getTimeZone(timeZone));
        return simpleDateFormat.format(date);
    }
}
Here, we have created formatDate method that accepts the parameters date(current date), dateFormat(a format that the date needs to be converted), and timeZone(time zone to convert given date to desired time zone)
DateFormat simpleDateFormat = new SimpleDateFormat(dateFormat);
We are using the java core "SimpleDateFormat" class to convert the date in our desired date format.
simpleDateFormat.setTimeZone(TimeZone.getTimeZone(timeZone));
This will set the given time zone. We are setting the Israel timezone. 

Output:
2021-08-24 12:25:52 
If you need a different format then simply change the dateFormat argument value for e.g
String dateFormat = "yyyy-MM-dd";
Output:
2021-08-24
Get the list of all TimeZones.

If you want to get all the time zones available then simply try using the following method.
import java.time.ZoneId;
import java.util.Set;

public static void visualizeAllTimeZone() {
        Set<String> zoneIds = ZoneId.getAvailableZoneIds();
        for (String id : zoneIds) {
            ZoneId zoneId = ZoneId.of(id);
            System.out.println(zoneId);
        }
    }


Output:

Asia/Aden
America/Cuiaba
Etc/GMT+9
Etc/GMT+8
Africa/Nairobi
America/Marigot
Asia/Aqtau
Pacific/Kwajalein
America/El_Salvador
Asia/Pontianak
Africa/Cairo
Pacific/Pago_Pago
Africa/Mbabane
Asia/Kuching
Pacific/Honolulu
Pacific/Rarotonga
America/Guatemala
Australia/Hobart
Europe/London
America/Belize
America/Panama
Asia/Chungking
America/Managua
America/Indiana/Petersburg
Asia/Yerevan
Europe/Brussels
GMT
Europe/Warsaw
America/Chicago
Asia/Kashgar
Chile/Continental
Pacific/Yap
CET
Etc/GMT-1
Etc/GMT-0
Europe/Jersey
America/Tegucigalpa
Etc/GMT-5
Europe/Istanbul
America/Eirunepe
Etc/GMT-4
America/Miquelon
Etc/GMT-3
Europe/Luxembourg
Etc/GMT-2
Etc/GMT-9
America/Argentina/Catamarca
Etc/GMT-8
Etc/GMT-7
Etc/GMT-6
Europe/Zaporozhye
Canada/Yukon
Canada/Atlantic
Atlantic/St_Helena
Australia/Tasmania
Libya
Europe/Guernsey
America/Grand_Turk
Asia/Samarkand
America/Argentina/Cordoba
Asia/Phnom_Penh
Africa/Kigali
Asia/Almaty
US/Alaska
Asia/Dubai
Europe/Isle_of_Man
America/Araguaina
Cuba
Asia/Novosibirsk
America/Argentina/Salta
Etc/GMT+3
Africa/Tunis
Etc/GMT+2
Etc/GMT+1
Pacific/Fakaofo
Africa/Tripoli
Etc/GMT+0
Israel
Africa/Banjul
Etc/GMT+7
Indian/Comoro
Etc/GMT+6
Etc/GMT+5
Etc/GMT+4
Pacific/Port_Moresby
US/Arizona
Antarctica/Syowa
Indian/Reunion
Pacific/Palau
Europe/Kaliningrad
America/Montevideo
Africa/Windhoek
Asia/Karachi
Africa/Mogadishu
Australia/Perth
Brazil/East
Etc/GMT
Asia/Chita
Pacific/Easter
Antarctica/Davis
Antarctica/McMurdo
Asia/Macao
America/Manaus
Africa/Freetown
Europe/Bucharest
Asia/Tomsk
America/Argentina/Mendoza
Asia/Macau
Europe/Malta
Mexico/BajaSur
Pacific/Tahiti
Africa/Asmera
Europe/Busingen
America/Argentina/Rio_Gallegos
Africa/Malabo
Europe/Skopje
America/Catamarca
America/Godthab
Europe/Sarajevo
Australia/ACT
GB-Eire
Africa/Lagos
America/Cordoba
Europe/Rome
Asia/Dacca
Indian/Mauritius
Pacific/Samoa
America/Regina
America/Fort_Wayne
America/Dawson_Creek
Africa/Algiers
Europe/Mariehamn
America/St_Johns
America/St_Thomas
Europe/Zurich
America/Anguilla
Asia/Dili
America/Denver
Africa/Bamako
Europe/Saratov
GB
Mexico/General
Pacific/Wallis
Europe/Gibraltar
Africa/Conakry
Africa/Lubumbashi
Asia/Istanbul
America/Havana
NZ-CHAT
Asia/Choibalsan
America/Porto_Acre
Asia/Omsk
Europe/Vaduz
US/Michigan
Asia/Dhaka
America/Barbados
Europe/Tiraspol
Atlantic/Cape_Verde
Asia/Yekaterinburg
America/Louisville
Pacific/Johnston
Pacific/Chatham
Europe/Ljubljana
America/Sao_Paulo
Asia/Jayapura
America/Curacao
Asia/Dushanbe
America/Guyana
America/Guayaquil
America/Martinique
Portugal
Europe/Berlin
Europe/Moscow
Europe/Chisinau
America/Puerto_Rico
America/Rankin_Inlet
Pacific/Ponape
Europe/Stockholm
Europe/Budapest
America/Argentina/Jujuy
Australia/Eucla
Asia/Shanghai
Universal
Europe/Zagreb
America/Port_of_Spain
Europe/Helsinki
Asia/Beirut
Asia/Tel_Aviv
Pacific/Bougainville
US/Central
Africa/Sao_Tome
Indian/Chagos
America/Cayenne
Asia/Yakutsk
Pacific/Galapagos
Australia/North
Europe/Paris
Africa/Ndjamena
Pacific/Fiji
America/Rainy_River
Indian/Maldives
Australia/Yancowinna
SystemV/AST4
Asia/Oral
America/Yellowknife
Pacific/Enderbury
America/Juneau
Australia/Victoria
America/Indiana/Vevay
Asia/Tashkent
Asia/Jakarta
Africa/Ceuta
Asia/Barnaul
America/Recife
America/Buenos_Aires
America/Noronha
America/Swift_Current
Australia/Adelaide
America/Metlakatla
Africa/Djibouti
America/Paramaribo
Asia/Qostanay
Europe/Simferopol
Europe/Sofia
Africa/Nouakchott
Europe/Prague
America/Indiana/Vincennes
Antarctica/Mawson
America/Kralendijk
Antarctica/Troll
Europe/Samara
Indian/Christmas
America/Antigua
Pacific/Gambier
America/Indianapolis
America/Inuvik
America/Iqaluit
Pacific/Funafuti
UTC
Antarctica/Macquarie
Canada/Pacific
America/Moncton
Africa/Gaborone
Pacific/Chuuk
Asia/Pyongyang
America/St_Vincent
Asia/Gaza
Etc/Universal
PST8PDT
Atlantic/Faeroe
Asia/Qyzylorda
Canada/Newfoundland
America/Kentucky/Louisville
America/Yakutat
Asia/Ho_Chi_Minh
Antarctica/Casey
Europe/Copenhagen
Africa/Asmara
Atlantic/Azores
Europe/Vienna
ROK
Pacific/Pitcairn
America/Mazatlan
Australia/Queensland
Pacific/Nauru
Europe/Tirane
Asia/Kolkata
SystemV/MST7
Australia/Canberra
MET
Australia/Broken_Hill
Europe/Riga
America/Dominica
Africa/Abidjan
America/Mendoza
America/Santarem
Kwajalein
America/Asuncion
Asia/Ulan_Bator
NZ
America/Boise
Australia/Currie
EST5EDT
Pacific/Guam
Pacific/Wake
Atlantic/Bermuda
America/Costa_Rica
America/Dawson
Asia/Chongqing
Eire
Europe/Amsterdam
America/Indiana/Knox
America/North_Dakota/Beulah
Africa/Accra
Atlantic/Faroe
Mexico/BajaNorte
America/Maceio
Etc/UCT
Pacific/Apia
GMT0
America/Atka
Pacific/Niue
Australia/Lord_Howe
Europe/Dublin
Pacific/Truk
MST7MDT
America/Monterrey
America/Nassau
America/Jamaica
Asia/Bishkek
America/Atikokan
Atlantic/Stanley
Australia/NSW
US/Hawaii
SystemV/CST6
Indian/Mahe
Asia/Aqtobe
America/Sitka
Asia/Vladivostok
Africa/Libreville
Africa/Maputo
Zulu
America/Kentucky/Monticello
Africa/El_Aaiun
Africa/Ouagadougou
America/Coral_Harbour
Pacific/Marquesas
Brazil/West
America/Aruba
America/North_Dakota/Center
America/Cayman
Asia/Ulaanbaatar
Asia/Baghdad
Europe/San_Marino
America/Indiana/Tell_City
America/Tijuana
Pacific/Saipan
SystemV/YST9
Africa/Douala
America/Chihuahua
America/Ojinaga
Asia/Hovd
America/Anchorage
Chile/EasterIsland
America/Halifax
Antarctica/Rothera
America/Indiana/Indianapolis
US/Mountain
Asia/Damascus
America/Argentina/San_Luis
America/Santiago
Asia/Baku
America/Argentina/Ushuaia
Atlantic/Reykjavik
Africa/Brazzaville
Africa/Porto-Novo
America/La_Paz
Antarctica/DumontDUrville
Asia/Taipei
Antarctica/South_Pole
Asia/Manila
Asia/Bangkok
Africa/Dar_es_Salaam
Poland
Atlantic/Madeira
Antarctica/Palmer
America/Thunder_Bay
Africa/Addis_Ababa
Asia/Yangon
Europe/Uzhgorod
Brazil/DeNoronha
Asia/Ashkhabad
Etc/Zulu
America/Indiana/Marengo
America/Creston
America/Punta_Arenas
America/Mexico_City
Antarctica/Vostok
Asia/Jerusalem
Europe/Andorra
US/Samoa
PRC
Asia/Vientiane
Pacific/Kiritimati
America/Matamoros
America/Blanc-Sablon
Asia/Riyadh
Iceland
Pacific/Pohnpei
Asia/Ujung_Pandang
Atlantic/South_Georgia
Europe/Lisbon
Asia/Harbin
Europe/Oslo
Asia/Novokuznetsk
CST6CDT
Atlantic/Canary
America/Knox_IN
Asia/Kuwait
SystemV/HST10
Pacific/Efate
Africa/Lome
America/Bogota
America/Menominee
America/Adak
Pacific/Norfolk
Europe/Kirov
America/Resolute
Pacific/Tarawa
Africa/Kampala
Asia/Krasnoyarsk
Greenwich
SystemV/EST5
America/Edmonton
Europe/Podgorica
Australia/South
Canada/Central
Africa/Bujumbura
America/Santo_Domingo
US/Eastern
Europe/Minsk
Pacific/Auckland
Africa/Casablanca
America/Glace_Bay
Canada/Eastern
Asia/Qatar
Europe/Kiev
Singapore
Asia/Magadan
SystemV/PST8
America/Port-au-Prince
Europe/Belfast
America/St_Barthelemy
Asia/Ashgabat
Africa/Luanda
America/Nipigon
Atlantic/Jan_Mayen
Brazil/Acre
Asia/Muscat
Asia/Bahrain
Europe/Vilnius
America/Fortaleza
Etc/GMT0
US/East-Indiana
America/Hermosillo
America/Cancun
Africa/Maseru
Pacific/Kosrae
Africa/Kinshasa
Asia/Kathmandu
Asia/Seoul
Australia/Sydney
America/Lima
Australia/LHI
America/St_Lucia
Europe/Madrid
America/Bahia_Banderas
America/Montserrat
Asia/Brunei
America/Santa_Isabel
Canada/Mountain
America/Cambridge_Bay
Asia/Colombo
Australia/West
Indian/Antananarivo
Australia/Brisbane
Indian/Mayotte
US/Indiana-Starke
Asia/Urumqi
US/Aleutian
Europe/Volgograd
America/Lower_Princes
America/Vancouver
Africa/Blantyre
America/Rio_Branco
America/Danmarkshavn
America/Detroit
America/Thule
Africa/Lusaka
Asia/Hong_Kong
Iran
America/Argentina/La_Rioja
Africa/Dakar
SystemV/CST6CDT
America/Tortola
America/Porto_Velho
Asia/Sakhalin
Etc/GMT+10
America/Scoresbysund
Asia/Kamchatka
Asia/Thimbu
Africa/Harare
Etc/GMT+12
Etc/GMT+11
Navajo
America/Nome
Europe/Tallinn
Turkey
Africa/Khartoum
Africa/Johannesburg
Africa/Bangui
Europe/Belgrade
Jamaica
Africa/Bissau
Asia/Tehran
WET
Europe/Astrakhan
Africa/Juba
America/Campo_Grande
America/Belem
Etc/Greenwich
Asia/Saigon
America/Ensenada
Pacific/Midway
America/Jujuy
Africa/Timbuktu
America/Bahia
America/Goose_Bay
America/Virgin
America/Pangnirtung
Asia/Katmandu
America/Phoenix
Africa/Niamey
America/Whitehorse
Pacific/Noumea
Asia/Tbilisi
America/Montreal
Asia/Makassar
America/Argentina/San_Juan
Hongkong
UCT
Asia/Nicosia
America/Indiana/Winamac
SystemV/MST7MDT
America/Argentina/ComodRivadavia
America/Boa_Vista
America/Grenada
Asia/Atyrau
Australia/Darwin
Asia/Khandyga
Asia/Kuala_Lumpur
Asia/Famagusta
Asia/Thimphu
Asia/Rangoon
Europe/Bratislava
Asia/Calcutta
America/Argentina/Tucuman
Asia/Kabul
Indian/Cocos
Japan
Pacific/Tongatapu
America/New_York
Etc/GMT-12
Etc/GMT-11
America/Nuuk
Etc/GMT-10
SystemV/YST9YDT
Europe/Ulyanovsk
Etc/GMT-14
Etc/GMT-13
W-SU
America/Merida
EET
America/Rosario
Canada/Saskatchewan
America/St_Kitts
Arctic/Longyearbyen
America/Fort_Nelson
America/Caracas
America/Guadeloupe
Asia/Hebron
Indian/Kerguelen
SystemV/PST8PDT
Africa/Monrovia
Asia/Ust-Nera
Egypt
Asia/Srednekolymsk
America/North_Dakota/New_Salem
Asia/Anadyr
Australia/Melbourne
Asia/Irkutsk
America/Shiprock
America/Winnipeg
Europe/Vatican
Asia/Amman
Etc/UTC
SystemV/AST4ADT
Asia/Tokyo
America/Toronto
Asia/Singapore
Australia/Lindeman
America/Los_Angeles
SystemV/EST5EDT
Pacific/Majuro
America/Argentina/Buenos_Aires
Europe/Nicosia
Pacific/Guadalcanal
Europe/Athens
US/Pacific
Europe/Monaco
You can select whatever time zone you need from the above list. 

In order to get the display name



import java.time.format.TextStyle;
import java.util.Locale;

System.out.println(zoneId.getDisplayName(TextStyle.FULL, Locale.US));
Share:

Friday, January 1, 2021

How to use static content in app root directory in grails

In Grails latest version, it provides static assets management mechanism. You can use different files under the corresponding folders.


All the images will go under the images directory, js files go under the javascripts directory and CSS goes under the stylesheets directory. These files will be accessed by the URL path start with "/assets/".

Now, what if you don't want to use this structure or need to use the root path for some static file content.

For this, grails provide another option to manage static resources. So, what you can do is create the /resources/public directory under /src/main/ and use static resources there.


For example, if you had a file under /src/main/resources/public/images/example.jpg path then you can access that file using https://example.com/static/images/example.jpg.

This means, your file can be accessed with "/static/" URL by default.

If you want to access the file in the app root directory, setup the following configuration under application.groovy

grails.resources.pattern = '/**'

Now, for the above example the file can be accessed with https://example.com/images/example.jpg URL and if the file is in /public/ directory that file can be accessed with root path https://example.com/file.js
Share:

Adding PWA support in existing VueJs application

In this tutorial, we are going to add the PWA support in the existing VueJs application.

1. Install Vue CLI

npm install -g @vue/cli
# OR
yarn global add @vue/cli

2. Add PWA in our application

Let's open the terminal or command prompt and go to the project directory and add PWA  to the project.
vue add pwa
This will add a couple of files and settings for PWA in our existing application.

1. registerServiceWorker.js under ./src directory.



/* eslint-disable no-console */

import { register } from 'register-service-worker'

if (process.env.NODE_ENV === 'production') {
  register(`${process.env.BASE_URL}service-worker.js`, {
    ready () {
      console.log(
        'App is being served from cache by a service worker.\n' +
        'For more details, visit https://goo.gl/AFskqB'
      )
    },
    registered () {
      console.log('Service worker has been registered.')
    },
    cached () {
      console.log('Content has been cached for offline use.')
    },
    updatefound () {
      console.log('New content is downloading.')
    },
    updated () {
      console.log('New content is available; please refresh.')
    },
    offline () {
      console.log('No internet connection found. App is running in offline mode.')
    },
    error (error) {
      console.error('Error during service worker registration:', error)
    }
  })
}
Inside this file, the service worker is registered, and also, we can see the different hooks implemented which we can use in different cases like when the update is found in the app when the user is offline etc.

2. Dependencies added

Under package.json you can see the register-service-worker and PWA plugin is added.


3. Added some icons

Under public/img/icons/ folder some icons are added for mobile, desktop display. Make sure to change your icons for different devices. For more detail on changing this follow the following article.


If you want to configure via config file follow this guide.

Besides this, registerServiceWorker is imported inside main.js file.

3. Build and Deploy the application.

Build and deploy the application, you can see the service worker is activated and running.


You can see the cached file inside cache storage.

By default, it uses default mode which means a service worker is generated for us. If you want to customize it follow the following articles.


To notify the users about the app update follow the following post.


Share: