Handling enumeration data with a database in JHipster 

Next, we'll run the application and verify that JHipster has created three entities and that they are available in the Entities menu to perform various CRUD operations. The first time we run the application, we will get an error, as follows:

org.springframework.dao.InvalidDataAccessApiUsageException: Unknown name value [Asia] for enum class [com.nilangpatel.domain.enumeration.Continent]; nested exception is java.lang.IllegalArgumentException: Unknown name value [Asia] for enum class [com.nilangpatel.domain.enumeration.Continent] at org.springframework.orm.jpa.EntityManagerFactoryUtils.convertJpaAccessExceptionIfPossible(EntityManagerFactoryUtils.java:367) ....

This error occurs while fetching continent data and trying to map it with the Continent enum data type.  The root cause is that we have defined the type of the continent column of the Country entity as a Continent enum. The actual value in that column, which is added through an insert script (from the MySQL site) is not exactly the same as the Continent enum values.  For example, the actual value in the database is Asia, while the corresponding enum is ASIA.

Another value of the continent column is North America, while the corresponding enum is NORTH_AMERICABecause of the limitations of enum in Java, we can't put a space in the middle of the value, and that is the reason we kept the values as NORTH_AMERICA, SOUTH_AMERICA, and so on. Because of this limitation, along with the case difference, you will get the previous exception while running the application.

As a workaround, we need to provide some sort of mapping of actual values in the database column, to enum values in Java. For this, we will use the JPA attribute converter mechanism. It is basically used to define a method to convert database values to Java representations of an attribute and vice versa. Open the Country.java class at the com.nilangpatel.domain package and update the annotation declaration for the continent attribute as follows:

@NotNull
//@Enumerated(EnumType.STRING) // commented original
@Convert(converter=ContinentEnumConvertor.class) // added newly
@Column(name = "continent", nullable = false)
private Continent continent;

Originally, it was defined as @Enumerated(EnumType.STRING), which was commented out with an added @Convert annotation. This annotation requires implementation of the javax.persistence.AttributeConverter interface. The implementation is provided by the ContinentEnumConvertor custom class as follows:

public class ContinentEnumConvertor implements AttributeConverter<Continent, String>{
@Override
public String convertToDatabaseColumn(Continent continent) {
return continent.getName();
}
@Override
public Continent convertToEntityAttribute(String continentValue) {
return Continent.getContinent(continentValue);
}
}

These two methods will convert the values between the database and the corresponding enum value in Java. We also need to do necessary changes in the Continent enum class, as follows:

public enum Continent {
ASIA("Asia"), EUROPE("Europe"), NORTH_AMERICA("North America"), AFRICA("Africa"), OCEANIA("Oceania"), ANTARCTICA("Antarctica"), SOUTH_AMERICA("South America");
private String name;
Continent(String name){
this.name=name;
}
public String getName() {
return this.name;
}
public static Continent getContinent(String name) {
Continent returnContinent = null;
switch(name){
case "Asia": returnContinent = Continent.ASIA;break;
case "Europe": returnContinent = Continent.EUROPE;break;
case "North America": returnContinent = Continent.NORTH_AMERICA;break;
case "Africa": returnContinent = Continent.AFRICA;break;
case "Oceania": returnContinent = Continent.OCEANIA;break;
case "Antarctica": returnContinent = Continent.ANTARCTICA;break;
case "South America": returnContinent = Continent.SOUTH_AMERICA;break;
default: returnContinent = null;
}
return returnContinent;
}
}

Run the application, and you will see the entities and JHipster allows to perform CRUD operation to only logged in user. However you will still see that the continent values are rendered as enum values, such as ASIA, NORTH_AMERICA, and so on, instead of the actual database column values. 

The reason for this is that, when enabling internationalization support at the time of application creation, JHipster generates the display value for various labels, error messages, and various enumerations. It nicely creates the key-value pair in a separate file for each artifact. These files are generated for each language-specific folder, under the src/main/webapp/i18n folder. For example, the language keys and their value for the Country entity are created in the src/main/webapp/i18n/en/country.json file.

Since our application only has one language, English, the language keys are only generated for the English language, under the en folder, as follows:

The keys and values are created in a JSON format. To understand its structure, open the country.json file, which looks as follows:

{
"gdpApp": {
"country": {
"home": {
"title": "Countries",
"createLabel": "Create a new Country",
},
"created": "A new Country is created with identifier {{ param }}",
"delete": {
"question": "Are you sure you want to delete Country {{ id }}?"
},
"detail": {
"title": "Country"
},
"code": "Code",
"name": "Name",
"continent": "Continent",
....
}
}
}

The title is accessible with the gdpApp.country.home.title key. This will be used in the HTML template. Open the country.component.html file under the /src/main/webapp/app/entities/country folder, and you will see the following code to use this key:

<div>
<h2 id="page-heading">
<span jhiTranslate="gdpApp.country.home.title">Countries</span>
....

JHipster has created various modules to support validations, enums, reading and parsing JSON, and so on. One of them, translation, supports internationalization. These are installed during JHipster installation as a jhipster-core package, under the node_modules folder created under the project directory. If you need to add further labels, you can place the key in the respective JSON file and use jhiTranslate to render the value. 

Now, back to our problem of showing the enum values on the screen for the Country entity, instead of the actual database value. This happens because the translation in continent.json is generated with an enum value, by default. You can change it as follows in order to show correct continent values on the screen:

 "ASIA": "Asia",
"EUROPE": "Europe",
"NORTH_AMERICA": "North America",
"AFRICA": "Africa",
"OCEANIA": "Oceania",
"ANTARCTICA": "Antarctica",
"SOUTH_AMERICA": "South America",

Everything should work as expected now. The admin is able to see all three entities, and can perform CRUD operations properly. We will now develop custom screens to show the GDP data by country.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.225.255.134