Home » Modeling » M2T (model-to-text transformation) » [Acceleo] Bad behaviour with Java classes with Acceleo runner
[Acceleo] Bad behaviour with Java classes with Acceleo runner [message #1782402] |
Thu, 22 February 2018 11:57  |
Eclipse User |
|
|
|
Hello,
For my generator, I have to use several of my Java classes storing static attributes and defining static methods.
When I launch the generator with the Acceleo runner, the first run has no problem and the generation works well, but from the second runs, it seems Acceleo doesn't use the good Java classes.
If I launch the generation with the Java runner, I have no problems.
Here is my example :
In the Main java class of my generator, I do this :
@Override
public void doGenerate(Monitor monitor) throws IOException {
// Init the services useful for the code generation.
EclipseLogServices.info("MainDAO.java", "doGenerate", "Start the pre processing tasks.");
LogServices.initLoggingService();
EclipseLogServices.info("MainDAO.java", "doGenerate", "End the pre processing tasks.");
// Launch the code generation.
super.doGenerate(monitor);
// Close the services useful for the code generation.
EclipseLogServices.info("MainDAO.java", "doGenerate", "Start the post processing tasks.");
LogServices.closeLoggingService();
EclipseLogServices.info("MainDAO.java", "doGenerate", "End the post processing tasks.");
In the LogServices class, I do this :
private static Logger logger = null;
private static FileHandler fileHandler = null;
public static void initLoggingService() {
try {
// Create and init the FileHandler
fileHandler = new FileHandler(LOG_FILE_PATH, false);
fileHandler.setFormatter(LogFormatter.getInstance());
fileHandler.setLevel(Level.ALL);
} catch (IOException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
// Init the logger
logger = Logger.getLogger(Logger.GLOBAL_LOGGER_NAME);
logger.setLevel(Level.ALL);
logger.setUseParentHandlers(false);
logger.addHandler(fileHandler);
info("LogServices.java", "initLoggingService", "Logger = " + logger);
}
public static void closeLoggingService() {
// Close and remove the FileHandler from the logger
fileHandler.close();
logger.removeHandler(fileHandler);
// Deallocate the Logger and the FileHandler
fileHandler = null;
logger = null;
}
public static void info(String className, String methodName, String message) {
// Build the LogRecord instance.
LogRecord logRecord = LogFormatter.buildLogRecord(Level.INFO, className, methodName, message);
// Log the info message.
logger.log(logRecord);
// Log an info message in the Error Log view of Eclipse.
EclipseLogServices.info(logRecord);
}
.... other logging methods...
The generation calls an Acceleo template logging messages by using the LogServices class, and from the second run, the calls of the LogServices methods from the Acceleo template fail because the LogServices.logger static attribute is null and I don't understand why.
For your information, the 4 logs generated by my EclipseLogServices in the doGenerate() method of the Main class are well displayed in all the runs, and even the one generated in the LogServices.initLoggingService method by the call of the info() method : an interesting thing is that the object id of the logger displayed in this last log is always the same in all the runs. It changes if I restart Eclipse : so it means the Logger class of the standard library is loaded by the JVM, and Java uses the same non-heap memory for all its runs in Eclipse.
Do you see what is wrong in this code ? The LogServices.closeLoggingService() is only called in the Main.doGenerate() method, so this is the only moment the LogServices.logger is null. So how can it be null when the methods of this class are called by the Acceleo template from the second run ? It seems the Main java class doesn't use the same loaded LogServices class as the Acceleo template, which uses only the one of the first run in which logger is null. Is there something to do in my Main class with my LogServices class ? I see that several post generation operations are executed by the generate() method of the AbstractAcceleoGenerator parent class, like clearing some services and loaded resources, could it will be the solution ? If yes, how can I declare this resource ?
I'm using Acceleo 3.4.1.
Thank you.
Best regards.
[Updated on: Fri, 23 February 2018 08:21] by Moderator
|
|
| |
Re: [Acceleo] Bad behaviour with Java classes with Acceleo runner [message #1782440 is a reply to message #1782439] |
Fri, 23 February 2018 09:00   |
Eclipse User |
|
|
|
Hi !
A run is a generation launched by clicking on the run application button in the toolbar of Eclipse. The run configuration I launch is of course an Acceleo Application, in which I configure the Project, the Main class, the Model, the Target, and I can choose too if I use the Acceleo runner or the Java runner.
My problem happens with the Acceleo Runner only. It seems Acceleo uses a classes cache for the interpretation of the Acceleo templates, which is not cleared at the end of a run and which is not used by the Main Java class of the generator.
So it seems at the first run, the same LogServices class is used by the Main Java class of the generator and the Acceleo templates interpreter, but from the second run, it seems the Acceleo templates interpreter continue to use the LogServices class loaded during the first run, which is not the same as the one loaded by the Main Java class which seems to be new on each run.
The Acceleo "doGenerate()" method is just called once on each run. I have changed anything else in the Main java class of the generator than the "doGenerate()" method you can read above.
[Updated on: Fri, 23 February 2018 09:17] by Moderator
|
|
| |
Re: [Acceleo] Bad behaviour with Java classes with Acceleo runner [message #1782452 is a reply to message #1782440] |
Fri, 23 February 2018 10:33   |
Eclipse User |
|
|
|
I confirm this strange behaviour.
I've changed the LogServices.logger static attribute to be public, and I've added the following logs in the Main java class :
@Override
public void doGenerate(Monitor monitor) throws IOException {
// Init the services useful for the code generation.
EclipseLogServices.info("MainDAO.java", "doGenerate", "Start the pre processing tasks.");
EclipseLogServices.info("MainDAO.java", "doGenerate", "Logger in main 1 is = " + LogServices.logger);
LogServices.initLoggingService();
EclipseLogServices.info("MainDAO.java", "doGenerate", "Logger in main 2 is = " + LogServices.logger);
PrePostProcessingCommonServices.setTargetFolder(getTargetFolder());
EclipseLogServices.info("MainDAO.java", "doGenerate", "End the pre processing tasks.");
// Launch the code generation.
try {
super.doGenerate(monitor);
} catch (IOException e) {
e.printStackTrace();
throw e;
} finally {
// Close the services useful for the code generation.
EclipseLogServices.info("MainDAO.java", "doGenerate", "Start the post processing tasks.");
EclipseLogServices.info("MainDAO.java", "doGenerate", "Logger in main 3 is = " + LogServices.logger);
LogServices.closeLoggingService();
EclipseLogServices.info("MainDAO.java", "doGenerate", "Logger in main 4 is = " + LogServices.logger);
EclipseLogServices.info("MainDAO.java", "doGenerate", "End the post processing tasks.");
}
}
I've changed too the different methods logging message to display at the end the value of the LogServices.logger attribute.
And here are the logs :
Run 1 after a restart of Eclipse :
!MESSAGE 2018-02-23 14:38:03.384 | INFO | MainDAO.java | doGenerate | Start the pre processing tasks.
!MESSAGE 2018-02-23 14:38:03.417 | INFO | MainDAO.java | doGenerate | Logger in main 1 is = null
!MESSAGE 2018-02-23 14:38:03.436 | INFO | LogServices.java | initLoggingService | Logger = java.util.logging.Logger@add9e5bjava.util.logging.Logger@add9e5b
!MESSAGE 2018-02-23 14:38:03.439 | INFO | MainDAO.java | doGenerate | Logger in main 2 is = java.util.logging.Logger@add9e5b
!MESSAGE 2018-02-23 14:38:03.444 | INFO | MainDAO.java | doGenerate | End the pre processing tasks.
!MESSAGE 2018-02-23 14:38:05.371 | SEVERE | RSA_design.emx | MainPackage | This main package is entirely invalid !java.util.logging.Logger@add9e5b [b]<<== This is a SEVERE log generated from an Acceleo template.[/b]
!MESSAGE 2018-02-23 14:38:05.383 | WARNING | RSA_design.emx | MainPackage | This main package is not complete.java.util.logging.Logger@add9e5b [b]<<== This is a WARNING log generated from an Acceleo template.[/b]
!MESSAGE 2018-02-23 14:38:05.396 | INFO | RSA_design.emx | MainPackage | This main package is called MainPackage.java.util.logging.Logger@add9e5b [b]<<== This is an INFO log generated from an Acceleo template.[/b]
!MESSAGE 2018-02-23 14:38:12.188 | INFO | MainDAO.java | doGenerate | Start the post processing tasks.
!MESSAGE 2018-02-23 14:38:12.200 | INFO | MainDAO.java | doGenerate | Logger in main 3 is = java.util.logging.Logger@add9e5b
!MESSAGE 2018-02-23 14:38:12.217 | INFO | MainDAO.java | doGenerate | Logger in main 4 is = null
!MESSAGE 2018-02-23 14:38:12.217 | INFO | MainDAO.java | doGenerate | End the post processing tasks.
Run 2 or more (without restarting Eclipse) :
!MESSAGE 2018-02-23 14:38:15.490 | INFO | MainDAO.java | doGenerate | Start the pre processing tasks.
!MESSAGE 2018-02-23 14:38:15.503 | INFO | MainDAO.java | doGenerate | Logger in main 1 is = null
!MESSAGE 2018-02-23 14:38:15.515 | INFO | LogServices.java | initLoggingService | Logger = java.util.logging.Logger@add9e5bjava.util.logging.Logger@add9e5b
!MESSAGE 2018-02-23 14:38:15.527 | INFO | MainDAO.java | doGenerate | Logger in main 2 is = java.util.logging.Logger@add9e5b
!MESSAGE 2018-02-23 14:38:15.530 | INFO | MainDAO.java | doGenerate | End the pre processing tasks.
!MESSAGE 2018-02-23 14:38:16.603 | SEVERE | RSA_design.emx | MainPackage | This main package is entirely invalid ![b]null[/b]
!MESSAGE
!STACK 0
[b]org.eclipse.acceleo.engine.AcceleoEvaluationException
...
Caused by: java.lang.NullPointerException
at org.myProject.LogServices.severe(LogServices.java:88)[/b]
!MESSAGE 2018-02-23 14:38:16.622 | WARNING | RSA_design.emx | MainPackage | This main package is not complete.[b]null[/b]
!MESSAGE
!STACK 0
[b]org.eclipse.acceleo.engine.AcceleoEvaluationException
...
Caused by: java.lang.NullPointerException
at org.myProject.LogServices.warning(LogServices.java:115)[/b]
!MESSAGE 2018-02-23 14:38:16.636 | INFO | RSA_design.emx | MainPackage | This main package is called MainPackage.[b]null[/b]
!MESSAGE
!STACK 0
[b]org.eclipse.acceleo.engine.AcceleoEvaluationException
...
Caused by: java.lang.NullPointerException
at org.myProject.LogServices.info(LogServices.java:142)[/b]
!MESSAGE 2018-02-23 14:38:24.446 | INFO | MainDAO.java | doGenerate | Start the post processing tasks.
!MESSAGE 2018-02-23 14:38:24.454 | INFO | MainDAO.java | doGenerate | Logger in main 3 is = java.util.logging.Logger@add9e5b
!MESSAGE 2018-02-23 14:38:24.464 | INFO | MainDAO.java | doGenerate | Logger in main 4 is = null
!MESSAGE 2018-02-23 14:38:24.473 | INFO | MainDAO.java | doGenerate | End the post processing tasks.
We can see in the logs of the second run, that the LogServices.logger is not null at the end of the init in the "doGenerate()" method, is null during the interpretation of the Acceleo templates, and is not null at the beginning of the services closing in the "doGenerate()" method. This is clearly not the same loaded class, contrary to the first run. It seems clearly that during the second run, the templates interpreter uses still the loaded LogServices class of the first run.
[Updated on: Fri, 23 February 2018 10:33] by Moderator
|
|
| | | |
Re: [Acceleo] Bad behaviour with Java classes with Acceleo runner [message #1782546 is a reply to message #1782474] |
Mon, 26 February 2018 05:37  |
Eclipse User |
|
|
|
Hello,
Given that you're using this on helios, I must admit I'm not entirely sure why you're ending up with this issue. Pre-luna, this launcher should be working fine. I don't think I'd be able to help more without being able to debug what's happening directly though. Good thing you've figured our a (kinda) workaround.
Regards
Laurent Goubet
Obeo
|
|
|
Goto Forum:
Current Time: Thu May 15 16:00:30 EDT 2025
Powered by FUDForum. Page generated in 0.07881 seconds
|