Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
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 16:57 Go to next message
Mad Vin is currently offline Mad VinFriend
Messages: 40
Registered: September 2013
Member
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 13:21]

Report message to a moderator

Re: [Acceleo] Bad behaviour with Java classes with Acceleo runner [message #1782439 is a reply to message #1782402] Fri, 23 February 2018 13:58 Go to previous messageGo to next message
Laurent Goubet is currently offline Laurent GoubetFriend
Messages: 1902
Registered: July 2009
Senior Member
Hi,

Can you explain a little more about what are "multiple runs"? If you're calling "doGenerate" multiple times, can you check that your "initLoggingService" is indeed called multiple times, and if you do have a non-null logger out of your "Logger.getLogger(Logger.GLOBAL_LOGGER_NAME)"? If your singleton logger is reset to null when you "close" it, then initializing it again will just return a null value if the singleton itself has been nulled. I can't really say what's happening here without being able to debug step by step and seeing what you're doing for "multiple runs" and checking how you initialize (or not) the logger for each.

Laurent
Re: [Acceleo] Bad behaviour with Java classes with Acceleo runner [message #1782440 is a reply to message #1782439] Fri, 23 February 2018 14:00 Go to previous messageGo to next message
Mad Vin is currently offline Mad VinFriend
Messages: 40
Registered: September 2013
Member
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 14:17]

Report message to a moderator

Re: [Acceleo] Bad behaviour with Java classes with Acceleo runner [message #1782446 is a reply to message #1782440] Fri, 23 February 2018 14:48 Go to previous messageGo to next message
Laurent Goubet is currently offline Laurent GoubetFriend
Messages: 1902
Registered: July 2009
Senior Member
The "Acceleo plug-in application" runner is no longer functional, since Luna (changes in the eclipse platform have broken this runner). I remember we've left it in for the people using acceleo in older version of Eclipse and thus could still use this option, with an error shown on the launch configuration dialog telling you that "it may no longer work due to changes in luna"...

I was pretty sure I had removed this option altogether a while ago to completely prevent people from using it, but it seems I was mistaken since it's obviously still there. Anyway, The error you have here stems from these very changes in luna which have broken that launcher: we can no longer install and uninstall plugins on the fly in the eclipse platform so you're getting stuck with an older version (the one of your first launch) every time you start your generator. Please switch to using the java application launcher, in the meantime I'll double-check why that runner hadn't been removed from the acceleo UI.

Laurent Goubet
Obeo
Re: [Acceleo] Bad behaviour with Java classes with Acceleo runner [message #1782452 is a reply to message #1782440] Fri, 23 February 2018 15:33 Go to previous messageGo to next message
Mad Vin is currently offline Mad VinFriend
Messages: 40
Registered: September 2013
Member
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 15:33]

Report message to a moderator

Re: [Acceleo] Bad behaviour with Java classes with Acceleo runner [message #1782454 is a reply to message #1782452] Fri, 23 February 2018 15:39 Go to previous messageGo to next message
Laurent Goubet is currently offline Laurent GoubetFriend
Messages: 1902
Registered: July 2009
Senior Member
The issues I mentionned above about the "acceleo plug-in application" runner are pretty deep rooted and do involve the class loading. Basically, you'll end up with multiple version of your workspace's generator plugin (and its dependencies if they are in the workspace) installed in your running eclipse, one for each launch, with the on-the-fly uninstallation not working, so many multiple same classes loaded in your class loader, which will provoke a multitude of different possible bugs. Singletons not being singletons are one such possible bug.
Re: [Acceleo] Bad behaviour with Java classes with Acceleo runner [message #1782455 is a reply to message #1782446] Fri, 23 February 2018 16:05 Go to previous messageGo to next message
Mad Vin is currently offline Mad VinFriend
Messages: 40
Registered: September 2013
Member
FYI : we are using Helios Service Release 2 Build id: 20110218-0911, not Luna.

The Acceleo runner is useful to manage the generation of the linked UML elements in the .emx files like href="platform:/resource/MyProject/RSA_design.emx#_Q-1zoGdpEeOyEMVTmZVd0p?MyPackage?". So to be able to use the Java runner only, I suppose we have to configure something in the Main java class of the generator to convert the URI of the linked .emx files ?

Have you a link or a simple example of code to explain how to proceed ? For example for the above href. If I want to replace "platform:/resource/" by "file:/tmp/" or by "../../" ? I have found no property in RSA to generate relative paths in the .emx files.

The Acceleo runner is also useful to run the generation in the debug mode to debug the templates and queries code step by step, which is impossible with the Java runner.

And we cannot use a more recent Eclipse or Acceleo version because we have to generate code with .emx files created with an old version of RSA (version 8), so the RSA plugins dependencies are the old versions of the Eclipse Projects plugins.

[Updated on: Fri, 23 February 2018 17:12]

Report message to a moderator

Re: [Acceleo] Bad behaviour with Java classes with Acceleo runner [message #1782474 is a reply to message #1782455] Fri, 23 February 2018 19:08 Go to previous messageGo to next message
Mad Vin is currently offline Mad VinFriend
Messages: 40
Registered: September 2013
Member
Ok, we have another project which uses a custom UriConverter, I see now how to proceed.

The solution is to create a new Java class implementing the URIConverter interface in which we implement the "normalize()" method to associate a URI to another one by adding it in the getURIMap(). And we use a URIConverter delegate for all the other methods to implement, which is the URIConverter created by default and stored in the ResourceSet of the Main generator class. Then in the "registerPackages()" method of the Main class of the generator, we set the URIConverter of the resourceSet parameter to use the one we have created.

Thanks for your support Laurent about the impossibility of fixing this problem of loaded classes including static members with the Acceleo runner.
With the solution I've given, we will generate the code with the Java runner, so we can do it outside Eclipse too, but we can still use the Acceleo runner to debug, taking into account it will work correctly during the first run only.

Best regards.
Re: [Acceleo] Bad behaviour with Java classes with Acceleo runner [message #1782546 is a reply to message #1782474] Mon, 26 February 2018 10:37 Go to previous message
Laurent Goubet is currently offline Laurent GoubetFriend
Messages: 1902
Registered: July 2009
Senior Member
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
Previous Topic:[MTL] Reading Opaque Expressions
Next Topic:[Acceleo]
Goto Forum:
  


Current Time: Sat Apr 20 05:57:39 GMT 2024

Powered by FUDForum. Page generated in 0.03578 seconds
.:: Contact :: Home ::.

Powered by: FUDforum 3.0.2.
Copyright ©2001-2010 FUDforum Bulletin Board Software

Back to the top