How to get command Line arguments in spring boot? - java

#SpringBootApplication
public class CommandLinetoolApplication {
#Value("${person.name}")
private String name;
public static void main(String... argv) {
SpringApplication.run(CommandLinetoolApplication.class, argv);
}
}
I am using eclipse so setting run configuration as
-Dspring-boot.run.arguments=--person.name=firstName
But when run my application,I am getting exception as
"Could not resolve placeholder 'person.name' in value "${person.name}"

This code works just fine (Spring Boot 2.1.4):
#SpringBootApplication
public class DemoApplication implements ApplicationRunner
{
#Value("${person.name}")
private String name;
public static void main( String[] args )
{
SpringApplication.run( DemoApplication.class, args );
}
#Override
public void run( ApplicationArguments args ) throws Exception
{
System.out.println( "Name: " + name );
}
}
Command line:
mvn spring-boot:run -Dspring-boot.run.arguments=--person.name=Test
The output:
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.1.4.RELEASE)
2019-04-28 22:51:09.741 INFO 73751 --- [ main] com.example.demo.DemoApplication : Starting DemoApplication on xxx-MacBook-Pro.local with PID 73751 (/Users/strelok/code/demo-sb/target/classes started by strelok in /Users/strelok/code/demo-sb)
2019-04-28 22:51:09.745 INFO 73751 --- [ main] com.example.demo.DemoApplication : No active profile set, falling back to default profiles: default
2019-04-28 22:51:10.943 INFO 73751 --- [ main] com.example.demo.DemoApplication : Started DemoApplication in 16.746 seconds (JVM running for 23.386)
Name: Test

You need to add a configuration property person.name=firstName in your application.properties
OR
Implement interface ApplicationRunner and override its run method(Correct way to read command line argument)
Example:
#SpringBootApplication
public class Application implements ApplicationRunner {
private static final Logger logger = LoggerFactory.getLogger(Application.class);
public static void main(String... args) throws Exception {
SpringApplication.run(Application.class, args);
}
#Override
public void run(ApplicationArguments args) throws Exception {
logger.info("Application started with command-line arguments: {}", Arrays.toString(args.getSourceArgs()));
logger.info("NonOptionArgs: {}", args.getNonOptionArgs());
logger.info("OptionNames: {}", args.getOptionNames());
for (String name : args.getOptionNames()){
logger.info("arg-" + name + "=" + args.getOptionValues(name));
}
boolean containsOption = args.containsOption("person.name");
logger.info("Contains person.name: " + containsOption);
}
}

You need to change your eclipse VM arguments as -Dperson.name=dhanraj
One more thing is there is no use to add private String name; in main class.
Because main method is static method, so you need to create object to access name
variable and ultimately new object gives you null value not the value you set dhanraj.
So Use this variable in Controller or Service part.

Related

Why is my OpenTelemetry java extension not working

I have created an extension to add some comment in the sql query. For this I have created a MySQLAddCommentInstrumentation.java class to make changes to query in Statement.java class.
Also there is one MySQLAddCommentInstrumentationModule.java class which adds this instrumentation (MySQLAddCommentInstrumentation) to its list.
When I build this extension and run my app, I do not see the comment in the query under db.statement zipkin log.
Instrumentation Class - MySQLAddCommentInstrumentation.java
Path - examples/extension/src/main/java/com/example/javaagent/mysqlinstrumentation/MySQLAddCommentInstrumentation.java
package com.example.javaagent.mysqlinstrumentation;
import static io.opentelemetry.javaagent.extension.matcher.AgentElementMatchers.implementsInterface;
import static net.bytebuddy.matcher.ElementMatchers.named;
import static net.bytebuddy.matcher.ElementMatchers.namedOneOf;
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer;
import net.bytebuddy.asm.Advice;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.matcher.ElementMatcher;
import net.bytebuddy.matcher.ElementMatchers;
public class MySQLAddCommentInstrumentation implements TypeInstrumentation {
#Override
public ElementMatcher<TypeDescription> typeMatcher() {
System.out.println("Inside MYSQL- 1.1");
return implementsInterface(named("java.sql.Statement"));
}
public void transform(TypeTransformer transformer) {
System.out.println("Inside MYSQL- 1.2");
transformer.applyAdviceToMethod(
namedOneOf("executeQuery")
.and(ElementMatchers.takesArgument(0, String.class))
.and(ElementMatchers.isPublic()),
MySQLAddCommentInstrumentation.class.getName() + "$StatementAddCommentAdvice");
System.out.println("Inside MYSQL- 1.3");
}
#SuppressWarnings("unused")
public static class StatementAddCommentAdvice {
#Advice.OnMethodEnter(suppress = Throwable.class)
public static void onEnter(#Advice.Argument(value = 0, readOnly = false) String sql) {
System.out.println("Inside MYSQL- 1.4");
sql = sql + " -- some comment";
System.out.println("Inside MYSQL- 1.5");
}
}
InstrumentationModule - MySQLAddCommentInstrumentationModule.java
Path - examples/extension/src/main/java/com/example/javaagent/mysqlinstrumentation/MySQLAddCommentInstrumentationModule.java
package com.example.javaagent.mysqlinstrumentation;
import static java.util.Collections.singletonList;
import com.google.auto.service.AutoService;
import io.opentelemetry.javaagent.extension.instrumentation.InstrumentationModule;
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
import io.opentelemetry.javaagent.extension.matcher.AgentElementMatchers;
import java.util.List;
import net.bytebuddy.matcher.ElementMatcher;
#AutoService(InstrumentationModule.class)
public final class MySQLAddCommentInstrumentationModule extends InstrumentationModule {
public MySQLAddCommentInstrumentationModule() {
super("jdbc");
}
#Override
public int order() {
return 1;
}
#Override
public ElementMatcher.Junction<ClassLoader> classLoaderMatcher() {
return AgentElementMatchers.hasClassesNamed("java.sql.Statement");
}
#Override
public List<TypeInstrumentation> typeInstrumentations() {
return singletonList(new MySQLAddCommentInstrumentation());
}
}
Code where this instrumentations is expected to run:
try {
Connection con = DriverManager.getConnection(url, uname, password);
Statement statement = con.createStatement();
System.out.println(query);
ResultSet result = statement.executeQuery(query);
System.out.println(query);
} catch (SQLException e) {
e.printStackTrace();
}
I have run ./gradlew build inside examples/extension and used that extension jar to run my application
java -javaagent:/Users/vaibhavpaharia/Downloads/opentelemetry-javaagent.jar \
-Dotel.javaagent.extensions=/Users/vaibhavpaharia/ok/opentelemetry-java-instrumentation/examples/extension/build/libs/opentelemetry-java-instrumentation-extension-demo-1.0-all.jar \
-Dotel.service.name=simpleapplication \
-Dotel.traces.exporter=zipkin \
-Dserver.port=8080 \
-jar /Users/vaibhavpaharia/Downloads/simpleproject/target/simpleproject-0.0.1-SNAPSHOT.jar
After running the application with agent and extension I see that other extensions are working fine which are present in the example folder.
Also, I tried changing the order method in MySQLAddCommentInstrumentationModule.java and returned 0 from there, in that case Inside MYSQL- 1.1, Inside MYSQL- 1.2 and Inside MYSQL- 1.3 got printed so it seems the new extension is recognised while running the application. It never prints Inside MYSQL- 1.4 and Inside MYSQL- 1.5. Also, the traces stop coming to zipkin.
OpenJDK 64-Bit Server VM warning: Sharing is only supported for boot loader classes because bootstrap classpath has been appended
[otel.javaagent 2023-01-05 14:50:31:010 +0530] [main] INFO io.opentelemetry.javaagent.tooling.VersionLogger - opentelemetry-javaagent - version: 1.20.2
Inside MYSQL- 1.1
Inside MYSQL- 1.2
Inside MYSQL- 1.3
[otel.javaagent 2023-01-05 14:50:34:068 +0530] [main] INFO io.opentelemetry.javaagent.shaded.instrumentation.jmx.engine.JmxMetricInsight - Empty JMX configuration, no metrics will be collected for InstrumentationScope io.opentelemetry.jmx
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v3.0.1)
2023-01-05T14:50:35.687+05:30 INFO 85143 --- [ main] c.e.s.SimpleprojectApplication : Starting SimpleprojectApplication v0.0.1-SNAPSHOT using Java 18.0.2 with PID 85143 (/Users/vaibhavpaharia/Downloads/simpleproject/target/simpleproject-0.0.1-SNAPSHOT.jar started by vaibhavpaharia in /Users/vaibhavpaharia)
2023-01-05T14:50:35.700+05:30 INFO 85143 --- [ main] c.e.s.SimpleprojectApplication : No active profile set, falling back to 1 default profile: "default"
2023-01-05T14:50:37.451+05:30 INFO 85143 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8080 (http)
2023-01-05T14:50:37.531+05:30 INFO 85143 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat]
2023-01-05T14:50:37.531+05:30 INFO 85143 --- [ main] o.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/10.1.4]
2023-01-05T14:50:37.643+05:30 INFO 85143 --- [ main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
2023-01-05T14:50:37.645+05:30 INFO 85143 --- [ main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 1859 ms
2023-01-05T14:50:38.254+05:30 INFO 85143 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path ''
2023-01-05T14:50:38.266+05:30 INFO 85143 --- [ main] c.e.s.SimpleprojectApplication : Started SimpleprojectApplication in 3.409 seconds (process running for 7.566)
You'll need to set the readOnly = false option on the #Argument annotation , otherwise the advice code will not overwrite the original value:
#Advice.OnMethodEnter(suppress = Throwable.class)
public static void onEnter(#Advice.Argument(value = 0, readOnly = false) String sql) {
System.out.println("Inside MYSQL-1.4");
sql = sql + " -- some comment";
System.out.println("Inside MYSQL- 1.5");
}

How to define and read array of objects from spring's application.properties?

In my Java class, I want to read a variable that will give me a list of tokens in one shot and my token is an object with fields as name, value, and enabled.
#Value("authorised_applications")
private List<Token> tokenList;
How do I define this in my application.properties file so that I can read all tokens at once.
For an instance, I have tokens like:
token1
- value: 123456,
- name: specialToken,
- enabled: true
token2
- value: 56173,
- name: newToken,
- enabled: false
I have tried other links but could not find a way to read this all at once.
Want to create bean like this
#ConfigurationProperties("authorised")
#Configuration
public class AppTokenConfiguration {
private final List<TokenStore.Token> tokenList = new ArrayList<>();
#Bean
public TokenStore getTokenStore() {
return new TokenStore(tokenList.stream().collect(Collectors.toMap(TokenStore.Token::getToken, Function.identity())));
}
}
Use #ConfigurationProperties with prefix on the Class which has properties to be configured from application.properties.
application.properties:
my.tokenList[0].name=test1
my.tokenList[0].value=test2
my.tokenList[0].enabled=true
my.tokenList[1].name=test3
my.tokenList[1].value=test4
my.tokenList[1].enabled=false
server.port=8080
Student.java
import java.util.ArrayList;
import java.util.List;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
#ConfigurationProperties("my")
#Component
public class Student {
private final List<Token> tokenList = new ArrayList<>();
public List<Token> getTokenList() {
return tokenList;
}
#Override
public String toString() {
return "TestNow [tokenList=" + tokenList + "]";
}
}
Token.java
public class Token {
private String value;
private String name;
private boolean enabled;
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public boolean isEnabled() {
return enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
#Override
public String toString() {
return "Token [value=" + value + ", name=" + name + ", enabled=" + enabled + "]";
}
}
ValidateStudent.java
import javax.annotation.PostConstruct;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
#Component
public class ValidateStudent {
#Autowired
private Student student;
#PostConstruct
private void init() {
System.out.println("printing Student Object---> " + student);
}
}
Proof(output):
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.6.0-SNAPSHOT)
2021-10-20 21:17:30.083 INFO 14632 --- [ main] c.e.S.SpringBootCollectionsApplication : Starting SpringBootCollectionsApplication using Java 14.0.2 on Machine with PID 14632 (D:\workspaces\Oct20_app_properties\SpringBootCollections\target\classes started by D1 in D:\workspaces\Oct20_app_properties\SpringBootCollections)
2021-10-20 21:17:30.088 INFO 14632 --- [ main] c.e.S.SpringBootCollectionsApplication : No active profile set, falling back to default profiles: default
2021-10-20 21:17:31.869 INFO 14632 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8080 (http)
2021-10-20 21:17:31.891 INFO 14632 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat]
2021-10-20 21:17:31.891 INFO 14632 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/9.0.53]
2021-10-20 21:17:32.046 INFO 14632 --- [ main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
2021-10-20 21:17:32.046 INFO 14632 --- [ main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 1869 ms
printing Student Object---> TestNow [tokenList=[Token [value=test2, name=test1, enabled=true], Token [value=test4, name=test3, enabled=false]]]
2021-10-20 21:17:32.654 INFO 14632 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path ''
2021-10-20 21:17:32.675 INFO 14632 --- [ main] c.e.S.SpringBootCollectionsApplication : Started SpringBootCollectionsApplication in 3.345 seconds (JVM running for 3.995)
Edit Answer:
BeanConfig Class:
#Configuration
public class AppConfig {
#Autowired
private AppTokenConfiguration appTokenConfiguration;
#Bean
public TokenStore getTokenStore() {
return new TokenStore(appTokenConfiguration.getTokenList().stream().collect(Collectors.toMap(TokenStore.Token::getToken, Function.identity())));
}
}
PropertyConfigClass:
#ConfigurationProperties("authorised")
#Component
public class AppTokenConfiguration {
private final List<TokenStore.Token> tokenList = new ArrayList<>();
public void getTokenList(){
return tokenList;
}
}

Class.getDeclaredMethods throwing NoClassDefFoundError for class method with no arguments and void return type

I want to get the names of all the public methods (void return type and no arguments) of a class1 which is dependent on some other class2.
I am loading class through UrlClassLoader. Now when i am calling getDeclaredMethods, it is throwing NoClassDefFoundError caused by ClassNotFoundException.
I am having 3 mvn modules as
SampleClassLoader: Using it to get the methods of class of Module1.
Module1: Its class using the reference to classes of Module2. And has a dependency of Module2 in its pom.xml also.
Module2
The whole module structure looks like:
Project Structure
ClassLoadingTest
|----- Module1
| |--- pom.xml
| |--- src/main/java/
| | |--- com.classloadingtest.module1
| | |
| | |--- Module1Class1.java
| | |--- Module1Class2.java
|
|----- Module2
| |--- pom.xml
| |--- src/main/java/
| | |--- com.classloadingtest.module2
| | |
| | |--- Module2Class.java
|
|----- SampleClassLoader
| |--- pom.xml
| |--- src/main/java/
| | |--- com.classloadingtest.sampleClassLoader
| | |
| | |--- SampleClassLoader.java
Module1Class1.java
public class Module1Class1 {
public void claas1Fun() {
Module2Class module2ClassObj = new Module2Class();
module2ClassObj.module2Fun();
}
}
Module1Class2.java
public class Module1Class2 {
public void class2Fun(){
try {
Module2Class module2ClassObj = new Module2Class();
module2ClassObj.module2Fun();
} catch(Exception e ){
}
}
}
Module2Class.java
public class Module2Class {
public void module2Fun(){
}
}
SampleClassLoader.java
public class SampleClassLoader {
public static void main(String[] args) {
try {
URL mainSourceClassPathURL = new URL("file:" + System.getProperty("user.dir") + "/ClassLoadingTest/Module1/target/classes/");
URL[] urls = { mainSourceClassPathURL};
ClassLoader classLoader = URLClassLoader.newInstance(urls);
Class<?> testCaseClass = classLoader.loadClass("com.classloadingtest.module1.Module1Class1");
Method method[] = testCaseClass.getDeclaredMethods();
for (int i = 0 ; i < method.length ; i++) {
System.out.println(method[i].getName());
}
} catch (Exception e){
e.printStackTrace();
}
}
}
Now, When Running the SampleClassLoader for class Module1Class1 prints
claas1Fun
But when running for class Module1Class2 it is giving NoClassDefFoundError as:
Exception in thread "main" java.lang.NoClassDefFoundError: com/classloadingtest/module2/Module2Class
at java.lang.Class.getDeclaredMethods0(Native Method)
at java.lang.Class.privateGetDeclaredMethods(Class.java:2701)
at java.lang.Class.getDeclaredMethods(Class.java:1975)
at com.classloadingtest.sampleClassLoader.SampleClassLoader.main(SampleClassLoader.java:26)
Caused by: java.lang.ClassNotFoundException: com.classloadingtest.module2.Module2Class
at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at java.net.FactoryURLClassLoader.loadClass(URLClassLoader.java:814)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
... 4 more
I am having two questions here that is:
When using try catch, why it is giving error?
If the class1 is already loaded at classLoader.loadClass then why getDeclaredMethods method need to load dependent classes?
Concerning the try-catch issue, the point is that java.lang.NoClassDefFoundError is not an Exception, is an Error which is a more severe kind of Throwable.
Errors are, generally speaking, unrecoverable (Like OutOfMemoryError or StackOverflowError, ...), so they are seldom catched.
If you want to catch NoClassDefFoundError you should add catch(NoClassDefFoundError e) to your try

JHipster 6.0.1 docker-compose deployment: Java heap space

I have 2 applications. App 1 is using JHipster 5.8.2 which I deploy to a Digital Ocean's droplet with 2GB RAM and, after pushing my image to gitlab's registry, I run it docker-compose -f app.yml up (which has _JAVA_OPTIONS=-Xmx512m -Xms256m) and everything runs perfect in about 45 seconds.
App 2 was generated with JHipster 6.0.1 (it's actually an upgrade of my App 1). I used a similar droplet from App 1 for my App 2: single core with 2GB RAM but it failed because of Java Heap Space. After this I changed my droplet to 4GB 2 core droplet and changed my app.yml config to this: _JAVA_OPTIONS=-Xmx3072m -Xms2048m but it still fails with the same issue and after 40 minutes.
After this error I tried running the image in my computer with 32GB, after 2 1/2 hours, the same issue arose.
This is how I packed my 6.0.1 app:
/mvnw verify -Pprod -DskipTests
./mvnw jib:build -Dimage=registry.gitlab.com/amatos/project
In my droplet:
docker-compose -f app.yml up -d
This should work, but it never passes the line Web application fully configured and after several minutes (depending on the amount of RAM), it fails.
Is there an extra step I'm missing?
FINDING:
After doing a lot of testing, I discovered that, by adding a custom DTO I get the Java heap space issue.
Generated DTO:
package com.facturapp.service.dto;
import javax.validation.constraints.*;
import java.io.Serializable;
import java.util.Objects;
import javax.persistence.Lob;
/**
* A DTO for the {#link com.facturapp.domain.Address} entity.
*/
public class AddressDTO implements Serializable {
private Long id;
#NotNull
private String name;
private String contact;
private String mobile;
private String address;
#Lob
private String note;
private Boolean delivery;
private Boolean invoicing;
private Boolean active;
private Long districtId;
private String districtName;
private Long partnerId;
private String partnerName;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getContact() {
return contact;
}
public void setContact(String contact) {
this.contact = contact;
}
public String getMobile() {
return mobile;
}
public void setMobile(String mobile) {
this.mobile = mobile;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getNote() {
return note;
}
public void setNote(String note) {
this.note = note;
}
public Boolean isDelivery() {
return delivery;
}
public void setDelivery(Boolean delivery) {
this.delivery = delivery;
}
public Boolean isInvoicing() {
return invoicing;
}
public void setInvoicing(Boolean invoicing) {
this.invoicing = invoicing;
}
public Boolean isActive() {
return active;
}
public void setActive(Boolean active) {
this.active = active;
}
public Long getDistrictId() {
return districtId;
}
public void setDistrictId(Long districtId) {
this.districtId = districtId;
}
public String getDistrictName() {
return districtName;
}
public void setDistrictName(String districtName) {
this.districtName = districtName;
}
public Long getPartnerId() {
return partnerId;
}
public void setPartnerId(Long partnerId) {
this.partnerId = partnerId;
}
public String getPartnerName() {
return partnerName;
}
public void setPartnerName(String partnerName) {
this.partnerName = partnerName;
}
#Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
AddressDTO addressDTO = (AddressDTO) o;
if (addressDTO.getId() == null || getId() == null) {
return false;
}
return Objects.equals(getId(), addressDTO.getId());
}
#Override
public int hashCode() {
return Objects.hashCode(getId());
}
#Override
public String toString() {
return "AddressDTO{" +
"id=" + getId() +
", name='" + getName() + "'" +
", contact='" + getContact() + "'" +
", mobile='" + getMobile() + "'" +
", address='" + getAddress() + "'" +
", note='" + getNote() + "'" +
", delivery='" + isDelivery() + "'" +
", invoicing='" + isInvoicing() + "'" +
", active='" + isActive() + "'" +
", district=" + getDistrictId() +
", district='" + getDistrictName() + "'" +
", partner=" + getPartnerId() +
", partner='" + getPartnerName() + "'" +
"}";
}
}
Custom DTO
package com.facturapp.service.dto;
import com.facturapp.domain.District;
/**
* A DTO for the {#link com.facturapp.domain.Address} entity.
*/
public class AddressFaDTO extends AddressDTO {
private District district;
public District getDistrict() {
return district;
}
public void setDistrict(District district) {
this.district = district;
}
}
The custom DTO is Address and extends the generated DTO. The generated DTO has a few fields, 2 of them are districtId (Long) and districtName (String), but my custom DTO also has district (District). The class District has a property Province which also has Region, which also has Country. So when I retrieve an Address I also get the district, province, region and country.
My custom Resource calls a custom service that retrieves my custom DTO with the district and all the other classes.
If I use the generated DTO I have no issue, but when I use my custom DTO, the app doesn't run and fails due to the Java Heap space.
Error logs
facturapp_1 | 2019-06-03 06:56:20.395 INFO 1 --- [ restartedMain] com.almasoft.facturapp.FacturApp : Starting FacturApp on c40efbe18b21 with PID 1 (/app/classes started by root in /)
facturapp_1 | 2019-06-03 06:56:20.407 INFO 1 --- [ restartedMain] com.almasoft.facturapp.FacturApp : The following profiles are active: prod,swagger
facturapp_1 | 2019-06-03 06:56:45.918 WARN 1 --- [ restartedMain] i.g.j.c.liquibase.AsyncSpringLiquibase : Warning, Liquibase took more than 5 seconds to start up!
facturapp_1 | 2019-06-03 06:56:57.351 INFO 1 --- [ restartedMain] c.a.facturapp.config.WebConfigurer : Web application configuration, using profiles: prod
facturapp_1 | 2019-06-03 06:56:57.353 INFO 1 --- [ restartedMain] c.a.facturapp.config.WebConfigurer : Web application fully configured
facturapp_1 | WARNING: An illegal reflective access operation has occurred
facturapp_1 | WARNING: Illegal reflective access by org.springframework.cglib.core.ReflectUtils (file:/app/libs/spring-core-5.1.6.RELEASE.jar) to method java.lang.ClassLoader.defineClass(java.lang.String,byte[],int,int,java.security.ProtectionDomain)
facturapp_1 | WARNING: Please consider reporting this to the maintainers of org.springframework.cglib.core.ReflectUtils
facturapp_1 | WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
facturapp_1 | WARNING: All illegal access operations will be denied in a future release
facturapp_1 | 2019-06-03 07:03:27.207 WARN 1 --- [ restartedMain] ConfigServletWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.context.ApplicationContextException: Failed to start bean 'documentationPluginsBootstrapper'; nested exception is com.google.common.util.concurrent.ExecutionError: java.lang.OutOfMemoryError: Java heap space
facturapp_1 | 2019-06-03 07:03:27.606 ERROR 1 --- [ restartedMain] o.s.boot.SpringApplication : Application run failed
facturapp_1 |
facturapp_1 | org.springframework.context.ApplicationContextException: Failed to start bean 'documentationPluginsBootstrapper'; nested exception is com.google.common.util.concurrent.ExecutionError: java.lang.OutOfMemoryError: Java heap space
facturapp_1 | at org.springframework.context.support.DefaultLifecycleProcessor.doStart(DefaultLifecycleProcessor.java:185)
facturapp_1 | at org.springframework.context.support.DefaultLifecycleProcessor.access$200(DefaultLifecycleProcessor.java:53)
facturapp_1 | at org.springframework.context.support.DefaultLifecycleProcessor$LifecycleGroup.start(DefaultLifecycleProcessor.java:360)
facturapp_1 | at org.springframework.context.support.DefaultLifecycleProcessor.startBeans(DefaultLifecycleProcessor.java:158)
facturapp_1 | at org.springframework.context.support.DefaultLifecycleProcessor.onRefresh(DefaultLifecycleProcessor.java:122)
facturapp_1 | at org.springframework.context.support.AbstractApplicationContext.finishRefresh(AbstractApplicationContext.java:893)
facturapp_1 | at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.finishRefresh(ServletWebServerApplicationContext.java:163)
facturapp_1 | at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:552)
facturapp_1 | at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:142)
facturapp_1 | at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:775)
facturapp_1 | at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:397)
facturapp_1 | at org.springframework.boot.SpringApplication.run(SpringApplication.java:316)
facturapp_1 | at com.facturapp.FacturApp.main(FacturApp.java:63)
facturapp_1 | at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
facturapp_1 | at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
facturapp_1 | at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
facturapp_1 | at java.base/java.lang.reflect.Method.invoke(Unknown Source)
facturapp_1 | at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49)
facturapp_1 | Caused by: com.google.common.util.concurrent.ExecutionError: java.lang.OutOfMemoryError: Java heap space
facturapp_1 | at com.google.common.cache.LocalCache$Segment.get(LocalCache.java:2049)
facturapp_1 | at com.google.common.cache.LocalCache.get(LocalCache.java:3953)
facturapp_1 | at com.google.common.cache.LocalCache.getOrLoad(LocalCache.java:3976)
facturapp_1 | at com.google.common.cache.LocalCache$LocalLoadingCache.get(LocalCache.java:4960)
facturapp_1 | at springfox.documentation.schema.CachingModelDependencyProvider.dependentModels(CachingModelDependencyProvider.java:58)
facturapp_1 | at springfox.documentation.schema.DefaultModelProvider.dependencies(DefaultModelProvider.java:128)
facturapp_1 | at springfox.documentation.schema.CachingModelProvider.dependencies(CachingModelProvider.java:68)
facturapp_1 | at springfox.documentation.spring.web.scanners.ApiModelReader.populateDependencies(ApiModelReader.java:136)
facturapp_1 | at springfox.documentation.spring.web.scanners.ApiModelReader.read(ApiModelReader.java:78)
facturapp_1 | at springfox.documentation.spring.web.scanners.ApiListingScanner.scan(ApiListingScanner.java:133)
facturapp_1 | at springfox.documentation.spring.web.scanners.ApiDocumentationScanner.scan(ApiDocumentationScanner.java:71)
facturapp_1 | at springfox.documentation.spring.web.plugins.DocumentationPluginsBootstrapper.scanDocumentation(DocumentationPluginsBootstrapper.java:101)
facturapp_1 | at springfox.documentation.spring.web.plugins.DocumentationPluginsBootstrapper.start(DocumentationPluginsBootstrapper.java:167)
facturapp_1 | at org.springframework.context.support.DefaultLifecycleProcessor.doStart(DefaultLifecycleProcessor.java:182)
facturapp_1 | ... 17 common frames omitted
facturapp_1 | Caused by: java.lang.OutOfMemoryError: Java heap space
facturapp_1 | at java.base/java.util.Arrays.copyOf(Unknown Source)
facturapp_1 | at java.base/java.util.ArrayList.grow(Unknown Source)
facturapp_1 | at java.base/java.util.ArrayList.addAll(Unknown Source)
facturapp_1 | at springfox.documentation.schema.DefaultModelDependencyProvider.resolvedPropertiesAndFields(DefaultModelDependencyProvider.java:181)
facturapp_1 | at springfox.documentation.schema.DefaultModelDependencyProvider.resolvedDependencies(DefaultModelDependencyProvider.java:120)
facturapp_1 | at springfox.documentation.schema.DefaultModelDependencyProvider.maybeFromRegularType(DefaultModelDependencyProvider.java:207)
facturapp_1 | at springfox.documentation.schema.DefaultModelDependencyProvider.resolvedPropertiesAndFields(DefaultModelDependencyProvider.java:183)
facturapp_1 | at springfox.documentation.schema.DefaultModelDependencyProvider.resolvedDependencies(DefaultModelDependencyProvider.java:120)
facturapp_1 | at springfox.documentation.schema.DefaultModelDependencyProvider.maybeFromRegularType(DefaultModelDependencyProvider.java:207)
facturapp_1 | at springfox.documentation.schema.DefaultModelDependencyProvider.resolvedPropertiesAndFields(DefaultModelDependencyProvider.java:183)
facturapp_1 | at springfox.documentation.schema.DefaultModelDependencyProvider.resolvedDependencies(DefaultModelDependencyProvider.java:120)
facturapp_1 | at springfox.documentation.schema.DefaultModelDependencyProvider.maybeFromCollectionElementType(DefaultModelDependencyProvider.java:220)
facturapp_1 | at springfox.documentation.schema.DefaultModelDependencyProvider.resolvedPropertiesAndFields(DefaultModelDependencyProvider.java:181)
facturapp_1 | at springfox.documentation.schema.DefaultModelDependencyProvider.resolvedDependencies(DefaultModelDependencyProvider.java:120)
facturapp_1 | at springfox.documentation.schema.DefaultModelDependencyProvider.maybeFromCollectionElementType(DefaultModelDependencyProvider.java:220)
facturapp_1 | at springfox.documentation.schema.DefaultModelDependencyProvider.resolvedPropertiesAndFields(DefaultModelDependencyProvider.java:181)
facturapp_1 | at springfox.documentation.schema.DefaultModelDependencyProvider.resolvedDependencies(DefaultModelDependencyProvider.java:120)
facturapp_1 | at springfox.documentation.schema.DefaultModelDependencyProvider.maybeFromCollectionElementType(DefaultModelDependencyProvider.java:220)
facturapp_1 | at springfox.documentation.schema.DefaultModelDependencyProvider.resolvedPropertiesAndFields(DefaultModelDependencyProvider.java:181)
facturapp_1 | at springfox.documentation.schema.DefaultModelDependencyProvider.resolvedDependencies(DefaultModelDependencyProvider.java:120)
facturapp_1 | at springfox.documentation.schema.DefaultModelDependencyProvider.maybeFromRegularType(DefaultModelDependencyProvider.java:207)
facturapp_1 | at springfox.documentation.schema.DefaultModelDependencyProvider.resolvedPropertiesAndFields(DefaultModelDependencyProvider.java:183)
facturapp_1 | at springfox.documentation.schema.DefaultModelDependencyProvider.resolvedDependencies(DefaultModelDependencyProvider.java:120)
facturapp_1 | at springfox.documentation.schema.DefaultModelDependencyProvider.dependentModels(DefaultModelDependencyProvider.java:79)
facturapp_1 | at springfox.documentation.schema.CachingModelDependencyProvider$1.load(CachingModelDependencyProvider.java:50)
facturapp_1 | at springfox.documentation.schema.CachingModelDependencyProvider$1.load(CachingModelDependencyProvider.java:48)
facturapp_1 | at com.google.common.cache.LocalCache$LoadingValueReference.loadFuture(LocalCache.java:3529)
facturapp_1 | at com.google.common.cache.LocalCache$Segment.loadSync(LocalCache.java:2278)
facturapp_1 | at com.google.common.cache.LocalCache$Segment.lockedGetOrLoad(LocalCache.java:2155)
facturapp_1 | at com.google.common.cache.LocalCache$Segment.get(LocalCache.java:2045)
facturapp_1 | at com.google.common.cache.LocalCache.get(LocalCache.java:3953)
facturapp_1 | at com.google.common.cache.LocalCache.getOrLoad(LocalCache.java:3976)
My questions are:
why am I having such issue for just extending a simple DTO?
how can I solve this issue?
My mistake was using a domain class as a field instead of the DTO class for Address.
The question is still why there is a memory issue when launching the app and not when the method using the faulty class is called.

Memory leak in my GWT application

I have a web application created with GWT that has a memory leak.
honestly, I can't produce this memory leak but when we deploy the application in the client environment with many users we face a memory leak problem.
I received this file maybe it can help me, it has the objects in the memory when the memory leak produced.
2'777'369'064 (62.72%) [32] 8 class */planning/canvas/shared/serializable/ActionCycleSZ 0x68759f768
|- 2'777'365'536 (62.72%) [256] 35 org/apache/catalina/loader/WebappClassLoader 0x688ce9df8
| |- 2'775'589'272 (62.68%) [48] 1 java/util/HashMap 0x688ceabe0
| | |- 2'775'589'224 (62.68%) [32'784] 3'533 array of java/util/HashMap$Entry 0x689af74c0
| | |- 2'763'509'944 (62.41%) [24] 2 java/util/HashMap$Entry 0x68a0b1f98
| | | |- 2'763'509'744 (62.41%) [40] 1 org/apache/catalina/loader/ResourceEntry 0x68a0b1fb0
| | | | |- 2'763'509'704 (62.41%) [32] 41 class
*/gwt/server/servlet/TaProjectsSessionManager 0x68653c8e8
| | | | |- 2'763'047'360 (62.4%) [32] 6 class */selfservice/SelfConfigurator 0x6875922a0
| | | | | |- 2'763'047'328 (62.4%) [16] 2 */gwt/server/servlet/TaProjectsSessionManager$1 0x689aee328
| | | | | | |- 2'154'573'968 (48.66%) [160] 30 */impl/HRSessionImpl 0x689ee49f8
| | | | | | | |- 2'138'350'824 (48.29%) [32] 3 java/util/Collections$SynchronizedMap 0x689ee4c70
| | | | | | | | |- 2'138'350'760 (48.29%) [64] 3 org/apache/commons/collections/map/LRUMap 0x689ee5218
| | | | | | | | | |- 2'134'913'368 (48.21%) [32] 2 org/apache/commons/collections/map/AbstractLinkedMap$LinkEntry 0x68a3573d0
| | | | | | | | | |- 3'437'328 (0.08%) [2'064] 121 array of org/apache/commons/collections/map/AbstractHashedMap$HashEntry 0x68a356bc8
| | | | | | | | | |- 16 (0%) [16] 1 org/apache/commons/collections/map/AbstractHashedMap$KeySet 0x69d443088
| | | | | | | | |- 32 (0%) [16] 2 java/util/Collections$SynchronizedSet 0x69d443098
| | | | | | | | |- 2'138'350'824 (48.29%) [32] 3 java/util/Collections$SynchronizedMap 0x689ee4c70
| | | | | | | |- 16'078'096 (0.36%) [104] 19 */impl/Dictionary 0x689ee4ad8
I conclude that the class ActionCycleSZ maybe produce the memory leak
this is ActionCycleSZ
public class ActionCycleSZ extends ActionDTO implements IsSerializable {
private CycleSZ bean;
public ActionCycleSZ() {
}
public ActionCycleSZ(Type actionType, CycleSZ bean ) {
super(actionType);
this.bean = bean;
}
public CycleSZ getBean(){
return bean;
}
public void setBean(CycleSZ bean){
this.bean = bean;
}
}
public class CycleSZ implements Serializable{
/**
*
*/
private static final long serialVersionUID = 1L;
String cycleLabel;
Date startDate;
Date endDate;
String startDateDTO;
String endDateDTO;
Integer numlign;
String accumulatedHours;
List<SiteSZ> listOfSites = new LinkedList<SiteSZ>();
//getter and setter
}
public class SiteSZ implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
int week;
String siteLabel;
Date startDate;
Date endDate;
String startHour;
String endHour;
String site;
String time;
String particularSlotTime;
Integer numlign;
DaySZ dayAttribute;
String accumulatedWeekHours;
Map<Util.WeekDays,DaySZ> mapAttributes = new LinkedHashMap<Util.WeekDays,DaySZ>();
boolean workedDay; //Flag for Exceptional Canevas Entry
boolean reposHebdo;
String contratId; //contratId for Exceptional Canevas Entry
ActionCycleSZ Contains the cycle and the action (create,delete,update)
this object will appear when the user create or update or delete this object
eventBus.addHandler(CycleSaveEvent.TYPE, new CycleSaveHandler() {
#Override
public void onCycleSaved(CycleSaveEvent event) {
final List<ActionCycleSZ> listCycleAction = new LinkedList<ActionCycleSZ>();
boolean newInsertion = getDetailsOfNewCycle(listCycleAction); //this methode can detect is there any new cycle and it will add actioncycleSZ
if (editedValuechange) {
getDeletedCycle(listCycleAction);
}
if (!newInsertion) getDetailsOfOldCycle(listCycleAction); getNotWorkedCycle(listOfNWSites,listCycleAction);
updateCycle(listCycleAction);
when the method updateCycle() called the listCycleAction will have all the cycles so the method will call an RPC service to save the cycles
This is updateCycle
public void updateCycle(final List<ActionCycleSZ> listCycleAction) {
//Call to service
new RpcCall2<String>() {
#Override
public void onFailure(Throwable caught) {
deletedListOfCycleSZ.clear();
view.setChantierGridUpdated(false);
}
#Override
public void onSuccess(final String message) {
isNewCycle=false;
SC.say(TAMessages.getMessage("ta.canvas.cycle.saved"), new BooleanCallback() {
#Override
public void execute(Boolean value) {
/* popup to make the user know that the cycle is saved */
}}}
#Override
protected void callService(AsyncCallback<AsyncCallback<String> callback) {
canvasServices.updateListActionCreatedCycle(listOfEmployees, listCycleAction, true, callback);
}
}.call();
I don't see anything that can make a memory leak so I install JProfiler to understand more my problem, I notice that the garbage collector for this object doesn't work whatever I call
canvasServices.updateListActionCreatedCycle(listOfEmployees,listCycleAction,true, callback);
even if the method is empty, On the other hand, the object will disappear in the memory if I don't give the object in the RPC call
what is the cause of the memory leak? am I on the right path?
I want to indicate that I am using GWT 2.5. can it be that GWT makes the memory leak ?

Categories