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

Fix code generation for Hazelcast cache provider #387

Open
wants to merge 9 commits into
base: main
Choose a base branch
from
25 changes: 19 additions & 6 deletions generators/micronaut-cache/generator.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { GENERATOR_BOOTSTRAP_APPLICATION } from 'generator-jhipster/generators';
import BaseApplicationGenerator from 'generator-jhipster/generators/base-application';
import { createNeedleCallback } from 'generator-jhipster/generators/base/support';
import { javaMainPackageTemplatesBlock } from 'generator-jhipster/generators/java/support';
import { getCacheProviderMavenDefinition } from './internal/dependencies.mjs';
import { getCacheProviderMavenDefinition, getCacheProviderGradleDefinition } from './internal/dependencies.mjs';

export default class extends BaseApplicationGenerator {
constructor(args, opts, features) {
Expand Down Expand Up @@ -53,7 +53,7 @@ export default class extends BaseApplicationGenerator {
files: [
{
...javaMainPackageTemplatesBlock(),
templates: ['config/CacheConfiguration.java'],
templates: [data => `config/CacheConfiguration${data.cacheProviderHazelcast ? '_hazelcast' : ''}.java`],
},
],
},
Expand All @@ -66,10 +66,23 @@ export default class extends BaseApplicationGenerator {
get [BaseApplicationGenerator.POST_WRITING_ENTITIES]() {
return this.asPostWritingTaskGroup({
addDependencies({ application, source }) {
const definition = getCacheProviderMavenDefinition(application.cacheProvider, application.javaDependencies);
source.addMavenDefinition?.(definition.base);
if (application.enableHibernateCache && definition.hibernateCache) {
source.addMavenDefinition?.(definition.hibernateCache);

if(application.buildToolMaven){
Comment on lines +69 to +70
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if(application.buildToolMaven){
const { javaDependencies, enableHibernateCache } = application;
if (application.cacheProviderHazelcast) {
source.addJavaDefinition(
{
versions: [{ name: 'hazelcast', version: javaDependencies.hazelcast }],
dependencies: [
javaxCacheApi,
{ groupId: 'com.hazelcast', artifactId: 'hazelcast', versionRef: 'hazelcast' },
{ groupId: 'io.micronaut.cache', artifactId: 'micronaut-cache-hazelcast' },
],
},
{
condition: enableHibernateCache,
dependencies: [{ groupId: 'com.hazelcast', artifactId: 'hazelcast-hibernate53', versionRef: 'hazelcast' }],
},
);
} else if (application.buildToolMaven){

const definition = getCacheProviderMavenDefinition(application.cacheProvider, application.javaDependencies);

source.addMavenDefinition?.(definition.base);
if (application.enableHibernateCache && definition.hibernateCache) {
source.addMavenDefinition?.(definition.hibernateCache);
}
}else if(application.buildToolGradle){
const definition = getCacheProviderGradleDefinition(application.cacheProvider, application.javaDependencies);

if(definition){
source.addGradleDependencies?.(definition.base.dependencies);
if (application.enableHibernateCache && definition.hibernateCache) {
source.addGradleDependencies?.(definition.hibernateCache.dependencies);
}
}
Comment on lines +77 to +85
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
}else if(application.buildToolGradle){
const definition = getCacheProviderGradleDefinition(application.cacheProvider, application.javaDependencies);
if(definition){
source.addGradleDependencies?.(definition.base.dependencies);
if (application.enableHibernateCache && definition.hibernateCache) {
source.addGradleDependencies?.(definition.hibernateCache.dependencies);
}
}

}
},
customizeFiles({ source, entities, application: { cacheProvider, enableHibernateCache } }) {
Expand Down
71 changes: 64 additions & 7 deletions generators/micronaut-cache/internal/dependencies.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -132,33 +132,39 @@ export const getCacheProviderMavenDefinition = (cacheProvider, javaDependencies)
base: {
properties: [
{
property: 'hazelcast-spring.version',
value: javaDependencies['hazelcast-spring'],
property: 'hazelcast.version',
value: javaDependencies['hazelcast'],
},
],
dependencies: [
javaxCacheApi,
{
groupId: 'com.hazelcast',
artifactId: 'hazelcast-spring',
artifactId: 'hazelcast',

version: '${hazelcast-spring.version}',
version: '${hazelcast.version}',
},
{
groupId: 'io.micronaut.cache',
artifactId: 'micronaut-cache-hazelcast',

version: '${micronaut.cache.version}',
},
],
},
hibernateCache: {
properties: [
{
property: 'hazelcast-hibernate53.version',
value: javaDependencies['hazelcast-hibernate53'],
property: 'hazelcast-hibernate.version',
value: javaDependencies['hazelcast-hibernate'],
},
],
dependencies: [
{
groupId: 'com.hazelcast',
artifactId: 'hazelcast-hibernate53',

version: '${hazelcast-hibernate53.version}',
version: '${hazelcast-hibernate.version}',
},
],
},
Expand Down Expand Up @@ -213,3 +219,54 @@ export const getCacheProviderMavenDefinition = (cacheProvider, javaDependencies)
};
return dependenciesForCache[cacheProvider];
};

export const getCacheProviderGradleDefinition = (cacheProvider, javaDependencies) => {
const dependenciesForCache = {
hazelcast: {
base: {
properties: [
{
property: 'hazelcast.version',
value: javaDependencies['hazelcast'],
},
],
dependencies: [
javaxCacheApi,
{
groupId: 'com.hazelcast',
artifactId: 'hazelcast',
scope: 'implementation',

version: '${hazelcast_version}',
Comment on lines +239 to +240
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
version: '${hazelcast_version}',
version: javaDependencies['hazelcast_version'],

},
{
groupId: 'io.micronaut.cache',
artifactId: 'micronaut-cache-hazelcast',
scope: 'implementation',

version: '${micronaut_cache_version}',
Comment on lines +246 to +247
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Inherited by the micronaut-platform bom.
Don't need to add a version.

Suggested change
version: '${micronaut_cache_version}',

},
],
},
hibernateCache: {
properties: [
{
property: 'hazelcast-hibernate.version',
value: javaDependencies['hazelcast-hibernate'],
},
],
dependencies: [
{
groupId: 'com.hazelcast',
artifactId: 'hazelcast-hibernate53',
scope: 'implementation',

version: '${hazelcast_hibernate_version}',
},
],
},
},
};

return dependenciesForCache[cacheProvider];
};
Original file line number Diff line number Diff line change
Expand Up @@ -145,4 +145,4 @@ public class CacheConfiguration {
}
cm.createCache(cacheName, jcacheConfiguration);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
package <%=packageName%>.config;

import java.util.Properties;

import <%=packageName%>.util.JHipsterProperties;
import io.micronaut.context.ApplicationContext;
import io.micronaut.context.annotation.Context;
import io.micronaut.context.annotation.Factory;
import io.micronaut.context.annotation.Primary;
import io.micronaut.context.env.Environment;
<%_ if (serviceDiscoveryAny) { _%>
import io.micronaut.discovery.DiscoveryClient;
import io.micronaut.discovery.ServiceInstance;
import io.micronaut.runtime.server.EmbeddedServer;
<%_ } _%>

import io.micronaut.cache.DynamicCacheManager;
import io.micronaut.cache.hazelcast.HazelcastCacheManager;
import io.micronaut.core.convert.ConversionService;
import io.micronaut.scheduling.TaskExecutors;
import io.reactivex.rxjava3.core.Flowable;

import com.hazelcast.config.Config;
import com.hazelcast.config.EvictionPolicy;
import com.hazelcast.config.ManagementCenterConfig;
import com.hazelcast.config.MapConfig;
import com.hazelcast.config.MaxSizePolicy;
import com.hazelcast.core.Hazelcast;
import com.hazelcast.core.HazelcastInstance;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import tech.jhipster.config.JHipsterConstants;
import jakarta.annotation.PreDestroy;
import jakarta.inject.Named;
import jakarta.inject.Singleton;
import java.util.List;
import java.util.concurrent.ExecutorService;
import javax.cache.CacheManager;

@Factory
public class CacheConfiguration {

private final Logger log = LoggerFactory.getLogger(CacheConfiguration.class);

private final Environment env;

private final JHipsterProperties jHipsterProperties;

<%_ if (serviceDiscoveryAny) { _%>
private final EmbeddedServer embeddedServer;

private final DiscoveryClient discoveryClient;
<%_ } _%>

public CacheConfiguration(Environment env<% if (serviceDiscoveryAny) { %>, EmbeddedServer embeddedServer, DiscoveryClient discoveryClient<%_ } _%>, JHipsterProperties jHipsterProperties) {
this.env = env;
<% if (serviceDiscoveryAny) { %>
this.embeddedServer = embeddedServer;
this.discoveryClient = discoveryClient;
<%_ } _%>
this.jHipsterProperties = jHipsterProperties;
}

@Singleton
@Context
@Primary
public HazelcastInstance hazelcastInstance(Config hazelcastConfig) {
return Hazelcast.newHazelcastInstance(hazelcastConfig);
}

@Singleton
public DynamicCacheManager cacheManager(HazelcastInstance hazelcastInstance,
@Named(TaskExecutors.IO) ExecutorService executorService) {
log.debug("Starting HazelcastCacheManager");
return new HazelcastCacheManager(ConversionService.SHARED, hazelcastInstance, executorService);
}

@PreDestroy
public void destroy() {
log.info("Closing Cache Manager");
Hazelcast.shutdownAll();
}

@Singleton
public Config hazelcastConfig() {
log.debug("Configuring Hazelcast");
HazelcastInstance hazelCastInstance = Hazelcast.getHazelcastInstanceByName("<%= baseName %>");
if (hazelCastInstance != null) {
log.debug("Hazelcast already initialized");
return hazelCastInstance.getConfig();
}

Config config = new Config();
config.setInstanceName("<%= baseName %>");
<%_ if (serviceDiscoveryAny) { _%>
config.getNetworkConfig().getJoin().getMulticastConfig().setEnabled(false);

if (this.discoveryClient == null) {
log.warn("No discovery service is set up, Hazelcast cannot create a cluster.");
} else {

String serviceId = env.getProperty("micronaut.application.name", String.class).orElse("<%= baseName %>");
log.debug("Configuring Hazelcast clustering for instanceId: {}", serviceId);

// In development, everything goes through 127.0.0.1, with a different port
if (env.getActiveNames().contains(JHipsterConstants.SPRING_PROFILE_DEVELOPMENT)) {
log.debug(
"Application is running with the \"dev\" profile, Hazelcast " + "cluster will only work with localhost instances"
);

config.getNetworkConfig().setPort(embeddedServer.getPort() + 5701);
config.getNetworkConfig().getJoin().getTcpIpConfig().setEnabled(true);

List<ServiceInstance> instances = Flowable.fromPublisher(discoveryClient.getInstances(serviceId)).blockingFirst();
for (ServiceInstance instance : instances) {
String clusterMember = "127.0.0.1:" + (instance.getPort() + 5701);
log.debug("Adding Hazelcast (dev) cluster member {}", clusterMember);
config.getNetworkConfig().getJoin().getTcpIpConfig().addMember(clusterMember);
}

} else { // Production configuration, one host per instance all using port 5701
config.getNetworkConfig().setPort(5701);
config.getNetworkConfig().getJoin().getTcpIpConfig().setEnabled(true);

List<ServiceInstance> instances = Flowable.fromPublisher(discoveryClient.getInstances(serviceId)).blockingFirst();
for (ServiceInstance instance : instances) {
String clusterMember = instance.getHost() + ":5701";
log.debug("Adding Hazelcast (prod) cluster member {}", clusterMember);
config.getNetworkConfig().getJoin().getTcpIpConfig().addMember(clusterMember);
}
}
}
<%_ } else { _%>
config.getNetworkConfig().setPort(5701);
config.getNetworkConfig().setPortAutoIncrement(true);

// In development, remove multicast auto-configuration
if (env.getActiveNames().contains(JHipsterConstants.SPRING_PROFILE_DEVELOPMENT)) {
System.setProperty("hazelcast.local.localAddress", "127.0.0.1");

config.getNetworkConfig().getJoin().getAwsConfig().setEnabled(false);
config.getNetworkConfig().getJoin().getMulticastConfig().setEnabled(false);
config.getNetworkConfig().getJoin().getTcpIpConfig().setEnabled(false);
}
<%_ } _%>
config.setManagementCenterConfig(new ManagementCenterConfig());
config.addMapConfig(initializeDefaultMapConfig(jHipsterProperties));
<%_ if (enableHibernateCache) { _%>
config.addMapConfig(initializeDomainMapConfig(jHipsterProperties));
<%_ } _%>
return config;
}

private MapConfig initializeDefaultMapConfig(JHipsterProperties jHipsterProperties) {
MapConfig mapConfig = new MapConfig("default");

/*
Number of backups. If 1 is set as the backup-count for example,
then all entries of the map will be copied to another JVM for
fail-safety. Valid numbers are 0 (no backup), 1, 2, 3.
*/
mapConfig.setBackupCount(jHipsterProperties.getCache().getHazelcast().getBackupCount());

/*
Valid values are:
NONE (no eviction),
LRU (Least Recently Used),
LFU (Least Frequently Used).
NONE is the default.
*/
mapConfig.getEvictionConfig().setEvictionPolicy(EvictionPolicy.LRU);

/*
Maximum size of the map. When max size is reached,
map is evicted based on the policy defined.
Any integer between 0 and Integer.MAX_VALUE. 0 means
Integer.MAX_VALUE. Default is 0.
*/
mapConfig.getEvictionConfig().setMaxSizePolicy(MaxSizePolicy.USED_HEAP_SIZE);

return mapConfig;
}

private MapConfig initializeDomainMapConfig(JHipsterProperties jHipsterProperties) {
MapConfig mapConfig = new MapConfig("<%= packageName %>.domain.*");
mapConfig.setTimeToLiveSeconds(jHipsterProperties.getCache().getHazelcast().getTimeToLiveSeconds());
return mapConfig;
}
}
5 changes: 5 additions & 0 deletions generators/micronaut/resources/gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,8 @@ gradle-git-properties = { id = 'com.gorylenko.gradle-git-properties', version =
openapi-generator = { id = 'org.openapi.generator', version = '7.8.0' }

shadow = { id = 'com.github.johnrengelman.shadow', version = '8.1.1' }

# hazelcast
hazelcast = { id = 'com.hazelcast:hazelcast', version = '5.4.0' }
# hazelcast-hibernate
hazelcast-hibernate = { id = 'com.hazelcast:hazelcast-hibernate53', version = '5.2.0' }
8 changes: 7 additions & 1 deletion generators/micronaut/resources/micronaut-platform.pom
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file is the published micronaut-platform bom, we have it embedded so we can a dependency version matching it.
It should be not changed.

Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,8 @@
<h2.version>2.3.232</h2.version>
<hamcrest.version>3.0</hamcrest.version>
<handlebars.version>4.3.1</handlebars.version>
<hazelcast.version>5.3.7</hazelcast.version>
<hazelcast.version>5.4.0</hazelcast.version>
<hazelcast-hibernate.version>5.2.0</hazelcast-hibernate.version>
<hibernate.reactive.version>2.3.1.Final</hibernate.reactive.version>
<hibernate.version>6.5.2.Final</hibernate.version>
<hikari.version>5.1.0</hikari.version>
Expand Down Expand Up @@ -664,6 +665,11 @@
<artifactId>hazelcast</artifactId>
<version>${hazelcast.version}</version>
</dependency>
<dependency>
<groupId>com.hazelcast</groupId>
<artifactId>hazelcast-hibernate53</artifactId>
<version>${hazelcast-hibernate.version}</version>
</dependency>
<dependency>
<groupId>org.infinispan</groupId>
<artifactId>infinispan-client-hotrod</artifactId>
Expand Down
9 changes: 0 additions & 9 deletions generators/micronaut/templates/build.gradle.ejs
Original file line number Diff line number Diff line change
Expand Up @@ -226,15 +226,6 @@ dependencies {
<%_ if (applicationTypeGateway) { _%>
implementation "org.apache.httpcomponents:httpclient"
<%_ } _%>
<%_ if (cacheProvider === 'hazelcast') { _%>
implementation "com.hazelcast:hazelcast"
<%_ } _%>
<%_ if (cacheProvider === 'hazelcast' && enableHibernateCache) { _%>
implementation "com.hazelcast:hazelcast-hibernate53"
<%_ } _%>
<%_ if (cacheProvider === 'hazelcast') { _%>
implementation "com.hazelcast:hazelcast-spring"
<%_ } _%>
<%_ if (cacheProvider === 'infinispan') { _%>
implementation "org.infinispan:infinispan-hibernate-cache-v53"
implementation "org.infinispan:infinispan-spring-boot-starter-embedded"
Expand Down
Loading
Loading