Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add caffeine cache implementation #117

Merged
merged 23 commits into from
Dec 2, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
5d63202
Add Quarkus cache dependency
avdev4j Nov 11, 2020
cedc7ca
Add cache UserService.java
avdev4j Nov 11, 2020
7997f42
Follow JHipster cache implementation for User entity
avdev4j Nov 13, 2020
4095506
Enable Hibernate second cache level for user
avdev4j Nov 13, 2020
a1cc975
Enable Hibernate second level cache for Authority
avdev4j Nov 13, 2020
75b0aa8
Improve code style
avdev4j Nov 12, 2020
33da6b2
Provide Quarkus cache each time we choose a cache
avdev4j Nov 13, 2020
f8ca426
Add cache dependency in Gradle
avdev4j Nov 13, 2020
fd01911
Override cacheManagerIsAvailable property with Quarkus caches
avdev4j Nov 13, 2020
db59bd0
Make integration-tests more consistent
avdev4j Nov 13, 2020
b325515
Enable User methods caching when enableHibernateCache
avdev4j Nov 13, 2020
6e8c66c
Add gradle tests
avdev4j Nov 13, 2020
926a1f3
Remove unused file
avdev4j Nov 13, 2020
ad87580
Add Hibernate cache support in Entity (with ReadOnly option too)
avdev4j Nov 13, 2020
e8de06b
Add application.properties for tests purpose
avdev4j Nov 16, 2020
cb8eca6
Move generation context into api and builder class to avoid duplicate…
avdev4j Nov 16, 2020
6731b69
Move server test generation context into api builder
avdev4j Nov 16, 2020
84dc839
Move client test generation context into api builder
avdev4j Nov 16, 2020
bb64303
Move common test generation context into api builder
avdev4j Nov 16, 2020
000d40b
Add default cache properties for User and Authority entities
avdev4j Nov 17, 2020
8695a72
Add needle api for hibernate second cache entity and relationships
avdev4j Nov 17, 2020
e0d1c03
Remove hints feature
avdev4j Nov 17, 2020
dbbbe34
add cache default properties
avdev4j Nov 18, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
10 changes: 6 additions & 4 deletions .github/workflows/smoke-test-imperative.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,13 @@ jobs:
node_version: [12.16.2]
os: [ubuntu-latest]
app:
- imperative-sql-jwt-maven-sample
- imperative-sql-jwt-maven-sqllight
- imperative-ngx-jwt-maven-mysql-caffeine
- imperative-ngx-jwt-maven-psql-nocache
- imperative-react-jwt-gradle-mysql-caffeine
include:
- app: imperative-sql-jwt-maven-sample
- app: imperative-sql-jwt-maven-sqllight
- app: imperative-ngx-jwt-maven-mysql-caffeine
- app: imperative-ngx-jwt-maven-psql-nocache
- app: imperative-react-jwt-gradle-mysql-caffeine
env:
JHI_APP: ${{ matrix.app }}
steps:
Expand Down
20 changes: 11 additions & 9 deletions generators/entity-server/files.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ const constants = require('generator-jhipster/generators/generator-constants');
const faker = require('faker');
const jhipsterUtils = require('generator-jhipster/generators/utils');

const NeedleApi = require('../needle-api');

const randexp = jhipsterUtils.RandexpWithFaker;
/* Constants use throughout */
const SERVER_MAIN_SRC_DIR = constants.SERVER_MAIN_SRC_DIR;
Expand Down Expand Up @@ -351,16 +353,16 @@ function writeFiles() {
}
this.addChangelogToLiquibase(`${this.changelogDate}_added_entity_${this.entityClass}`);
}
}
},

if (['ehcache', 'caffeine', 'infinispan', 'redis'].includes(this.cacheProvider) && this.enableHibernateCache) {
this.addEntityToCache(
this.asEntity(this.entityClass),
this.relationships,
this.packageName,
this.packageFolder,
this.cacheProvider
);
}
updateCacheConfiguration() {
if (this.enableHibernateCache) {
new NeedleApi(this).quarkusServerCache.addEntityConfigurationToPropertiesFile(
this.asEntity(this.entityClass),
this.relationships,
this.packageName
);
}
},

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ import com.fasterxml.jackson.annotation.JsonIgnore;
import io.swagger.annotations.ApiModel;
<%_ } if (!hasDto && importApiModelProperty === true) { _%>
import io.swagger.annotations.ApiModelProperty;
<%_ } if (readOnly) { _%>
<%_ } if (enableHibernateCache) { _%>
import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;
<%_ } if (hasTextBlob === true || (fieldsContainUUID === true && ['mysql', 'mariadb'].includes(prodDatabaseType))) { _%>
Expand Down Expand Up @@ -149,9 +149,9 @@ import static org.springframework.data.couchbase.core.mapping.id.GenerationStrat
<%_ if (databaseType === 'sql') { _%>
@Entity
@Table(name = "<%= entityTableName %>")
<%_ if (readOnly) { _%>
@Cache(usage = CacheConcurrencyStrategy.READ_ONLY)
<%_ } _%>
<%_ if (enableHibernateCache) { _%>
<% if (readOnly) { %>@Cache(usage = CacheConcurrencyStrategy.READ_ONLY)<% } else { %>@Cacheable<% } %>
<%_ } _%>
<%_ } _%>
<%_ if (databaseType === 'mongodb') { _%>
@Document(collection = "<%= entityTableName %>")
Expand Down Expand Up @@ -288,8 +288,8 @@ public class <%= asEntity(entityClass) %> extends PanacheEntityBase implements S
if (databaseType === 'sql') {
_%>
@OneToMany(mappedBy = "<%= otherEntityRelationshipName %>")
<%_ if (readOnly) { _%>
@Cache(usage = CacheConcurrencyStrategy.READ_ONLY)
<%_ if (enableHibernateCache) { _%>
@Cache(usage = CacheConcurrencyStrategy.<% if (readOnly) { %>READ_ONLY<% } else { %>READ_WRITE<% } %>)
<%_ } _%>
<%_ } else if (databaseType === 'mongodb' || databaseType === 'couchbase') {
if (databaseType === 'mongodb') { _%>
Expand Down Expand Up @@ -333,9 +333,9 @@ public class <%= asEntity(entityClass) %> extends PanacheEntityBase implements S
<%_ } else if (relationshipType === 'many-to-many') {
if (databaseType === 'sql') { _%>
@ManyToMany<% if (ownerSide === false) { %>(mappedBy = "<%= otherEntityRelationshipNamePlural %>")<% } %>
<%_ if (readOnly) { _%>
@Cache(usage = CacheConcurrencyStrategy.READ_ONLY)
<%_ } _%>
<%_ if (enableHibernateCache) { _%>
@Cache(usage = CacheConcurrencyStrategy.<% if (readOnly) { %>READ_ONLY<% } else { %>READ_WRITE<% } %>)
<%_ } _%>
<%_ if (ownerSide === true) {
if (relationshipValidate) { _%>
<%- include(fetchFromInstalledJHipster('entity-server/templates') + '/src/main/java/package/domain/relationship_validators', {
Expand Down
7 changes: 6 additions & 1 deletion generators/generator-quarkus-constants.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
const DEFAULT_DATA_ACCESS = 'activeRecord';
const QUARKUS_VERSION = '1.10.2.Final';

const CACHE_MAXIMUM_SIZE = 100;
const CACHE_EXPIRE_AFTER_WRITE = '3600S';

const constants = {
DEFAULT_DATA_ACCESS,
QUARKUS_VERSION
QUARKUS_VERSION,
CACHE_MAXIMUM_SIZE,
CACHE_EXPIRE_AFTER_WRITE
};

module.exports = constants;
25 changes: 25 additions & 0 deletions generators/needle-api.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/**
* Copyright 2013-2020 the original author or authors from the JHipster project.
*
* This file is part of the JHipster project, see https://www.jhipster.tech/
* for more information.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
const ServerCache = require('./server/needle-api/needle-server-cache');

module.exports = class NeedleApi {
constructor(generator) {
this.quarkusServerCache = new ServerCache(generator);
}
};
10 changes: 5 additions & 5 deletions generators/server/files.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,7 @@ const jhipsterFiles = require('generator-jhipster/generators/server/files').serv
/* Constants use throughout */
const INTERPOLATE_REGEX = constants.INTERPOLATE_REGEX;
const DOCKER_DIR = constants.DOCKER_DIR;
// const TEST_DIR = constants.TEST_DIR;
const SERVER_MAIN_SRC_DIR = constants.SERVER_MAIN_SRC_DIR;
const SERVER_MAIN_RES_DIR = constants.SERVER_MAIN_RES_DIR;
const SERVER_TEST_SRC_DIR = constants.SERVER_TEST_SRC_DIR;
const SERVER_TEST_RES_DIR = constants.SERVER_TEST_RES_DIR;
const { SERVER_MAIN_SRC_DIR, SERVER_MAIN_RES_DIR, SERVER_TEST_SRC_DIR, SERVER_TEST_RES_DIR } = constants;

const serverFiles = {
serverBuild: [
Expand Down Expand Up @@ -76,6 +72,10 @@ const serverFiles = {
'application.properties',
'resources-config.json'
]
},
{
path: SERVER_TEST_RES_DIR,
templates: ['application.properties']
}
],
serverTestSupport: [
Expand Down
17 changes: 13 additions & 4 deletions generators/server/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ const os = require('os');
const ServerGenerator = require('generator-jhipster/generators/server');
const prompts = require('./prompts');
const writeFiles = require('./files').writeFiles;
const quarkusVersion = require('../generator-quarkus-constants').QUARKUS_VERSION;
const { QUARKUS_VERSION, CACHE_MAXIMUM_SIZE, CACHE_EXPIRE_AFTER_WRITE } = require('../generator-quarkus-constants');

module.exports = class extends ServerGenerator {
constructor(args, opts) {
Expand All @@ -26,7 +26,9 @@ module.exports = class extends ServerGenerator {
const phaseFromJHipster = super._initializing();
const phaseFromQuarkus = {
defineQuarkusConstants() {
this.quarkusVersion = quarkusVersion;
this.quarkusVersion = QUARKUS_VERSION;
this.CACHE_MAXIMUM_SIZE = CACHE_MAXIMUM_SIZE;
this.CACHE_EXPIRE_AFTER_WRITE = CACHE_EXPIRE_AFTER_WRITE;
}
};
return { ...phaseFromJHipster, ...phaseFromQuarkus };
Expand All @@ -42,8 +44,15 @@ module.exports = class extends ServerGenerator {
}

get configuring() {
// Here we are not overriding this phase and hence its being handled by JHipster
return super._configuring();
const phaseFromJHipster = super._configuring();
const phaseFromQuarkus = {
configureGlobalQuarkus() {
// Override JHipster cacheManagerIsAvailable property to only handle Quarkus caches
this.cacheManagerIsAvailable = ['caffeine'].includes(this.cacheProvider);
}
};

return { ...phaseFromJHipster, ...phaseFromQuarkus };
}

get default() {
Expand Down
40 changes: 40 additions & 0 deletions generators/server/needle-api/needle-server-cache.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
const chalk = require('chalk');
const needleServerCache = require('generator-jhipster/generators/server/needle-api/needle-server-cache');
const constants = require('generator-jhipster/generators/generator-constants');
const { CACHE_MAXIMUM_SIZE, CACHE_EXPIRE_AFTER_WRITE } = require('../../generator-quarkus-constants');

const { SERVER_MAIN_RES_DIR } = constants;

module.exports = class extends needleServerCache {
addEntityConfigurationToPropertiesFile(entityClass, relationships, packageName) {
const errorMessage = chalk.yellow(`\nUnable to add ${entityClass} to application.properties file.`);
const cacheName = `${packageName}.domain.${entityClass}`;
const applicationPropertiesFileName = `${SERVER_MAIN_RES_DIR}application.properties`;
const needle = 'jhipster-quarkus-needle-hibernate-cache-add-entry';
const rewriteFileModel = this.generateFileModel(
applicationPropertiesFileName,
needle,
`quarkus.hibernate-orm.cache."${cacheName}".expiration.max-idle=${CACHE_EXPIRE_AFTER_WRITE}\n` +
`quarkus.hibernate-orm.cache."${cacheName}".memory.object-count=${CACHE_MAXIMUM_SIZE}`
);

this.addBlockContentToFile(rewriteFileModel, errorMessage);

relationships.forEach(relationship => {
const relationshipType = relationship.relationshipType;
if (relationshipType === 'one-to-many' || relationshipType === 'many-to-many') {
const rewriteFileModelWithRelationships = this.generateFileModel(
applicationPropertiesFileName,
needle,
`quarkus.hibernate-orm.cache."${cacheName}.${
relationship.relationshipFieldNamePlural
}".expiration.max-idle=${CACHE_EXPIRE_AFTER_WRITE}\n` +
`quarkus.hibernate-orm.cache."${cacheName}.${
relationship.relationshipFieldNamePlural
}".memory.object-count=${CACHE_MAXIMUM_SIZE}`
);
this.addBlockContentToFile(rewriteFileModelWithRelationships, errorMessage);
}
});
}
};
83 changes: 43 additions & 40 deletions generators/server/prompts.js
Original file line number Diff line number Diff line change
Expand Up @@ -189,46 +189,49 @@ function askForServerSideOpts(meta) {
].concat(constants.SQL_DB_OPTIONS.find(it => it.value === response.prodDatabaseType)),
default: 0
},
// ,
// {
// when: () => !reactive,
// type: 'list',
// name: 'cacheProvider',
// message: 'Do you want to use the Spring cache abstraction?',
// choices: [
// {
// value: 'ehcache',
// name: 'Yes, with the Ehcache implementation (local cache, for a single node)'
// },
// {
// value: 'caffeine',
// name: 'Yes, with the Caffeine implementation (local cache, for a single node)'
// },
// {
// value: 'hazelcast',
// name:
// 'Yes, with the Hazelcast implementation (distributed cache, for multiple nodes, supports rate-limiting for gateway applications)'
// },
// {
// value: 'infinispan',
// name: '[BETA] Yes, with the Infinispan implementation (hybrid cache, for multiple nodes)'
// },
// {
// value: 'memcached',
// name:
// 'Yes, with Memcached (distributed cache) - Warning, when using an SQL database, this will disable the Hibernate 2nd level cache!'
// },
// {
// value: 'redis',
// name: 'Yes, with the Redis implementation'
// },
// {
// value: 'no',
// name: 'No - Warning, when using an SQL database, this will disable the Hibernate 2nd level cache!'
// }
// ],
// default: applicationType === 'microservice' || applicationType === 'uaa' ? 2 : 0
// },
{
when: () => !reactive,
type: 'list',
name: 'cacheProvider',
message: 'Do you want to use the Quarkus cache abstraction?',
choices: [
/*
{
value: 'ehcache',
name: 'Yes, with the Ehcache implementation (local cache, for a single node)'
},
*/
{
value: 'caffeine',
name: 'Yes, with the Caffeine implementation (local cache, for a single node)'
},
/*
{
value: 'hazelcast',
name:
'Yes, with the Hazelcast implementation (distributed cache, for multiple nodes, supports rate-limiting for gateway applications)'
},
{
value: 'infinispan',
name: '[BETA] Yes, with the Infinispan implementation (hybrid cache, for multiple nodes)'
},
{
value: 'memcached',
name:
'Yes, with Memcached (distributed cache) - Warning, when using an SQL database, this will disable the Hibernate 2nd level cache!'
},
{
value: 'redis',
name: 'Yes, with the Redis implementation'
},
*/
{
value: 'no',
name: 'No - Warning, when using an SQL database, this will disable the Hibernate 2nd level cache!'
}
]
// default: applicationType === 'microservice' || applicationType === 'uaa' ? 2 : 0
},
{
when: response => response.databaseType === 'sql' && !reactive,
type: 'confirm',
Expand Down
3 changes: 3 additions & 0 deletions generators/server/templates/quarkus/build.gradle.ejs
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,9 @@ dependencies {
implementation "io.quarkus:quarkus-elytron-security"
implementation "io.quarkus:quarkus-smallrye-jwt"
implementation "io.quarkus:quarkus-smallrye-openapi"
<%_ if (cacheManagerIsAvailable) { _%>
implementation 'io.quarkus:quarkus-cache'
<%_ } _%>
implementation "io.quarkus:quarkus-smallrye-health"
implementation "io.quarkus:quarkus-micrometer"
implementation "io.micrometer:micrometer-registry-prometheus"
Expand Down
3 changes: 0 additions & 3 deletions generators/server/templates/quarkus/gradle.properties.ejs
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,7 @@ log4j2_mock_version=0.0.2
<%_ if (enableSwaggerCodegen) { _%>
jackson_databind_nullable_version=<%= JACKSON_DATABIND_NULLABLE_VERSION %>
<%_ } _%>
<%_ if (cacheProvider === 'caffeine') { _%>
caffeine_version=2.8.1
typesafe_config_version=1.4.0
<%_ } _%>
liquibase_hibernate5_version=3.8
liquibaseTaskPrefix=liquibase

Expand Down