0

We are migrating a system written in C to Java and must retain existing processes (no debate). We currently "embed" compile-time information into the C application using the C preprocessor, for example:

cc -o xxx.o -DCOMP_ARG='"compile time arg"' xxx.c

The xxx.c file can then use "COMP_ARG" and its value will be embedded in the code and we have little worry about it being changed inadvertently.

We realize Java likes to use properties files, however, our requirements are such that some information ** ** be embedded in the code, so properties files are not an option - these certain values cannot be specified at runtime. To illustrate the point, such data could be a date-stamp of when the file was compiled, but the exact data is irrelevant to the question.

We are looking for a way to specify at compile time various values that are available to the Java code. We are quite aware that Java does not have a pre-processor as does C, so the mechanism would be different.

Our current solution is using a code generation step (Maven), which does work, however, Eclipse is wreaking havoc trying to deal with the source files so that we had turn off "Build Automatically". We really want to find a more robust solution.

We appreciate any help, thanks.

Jim
  • 35
  • 1
  • 10
  • properties maven processing of properties? What do you mean by "Eclipse is wreaking havoc trying to deal with the source files"? Can you post a sample of your generated file? –  Feb 15 '17 at 18:51
  • Maybe http://stackoverflow.com/questions/25377900/how-to-create-a-dynamic-interface-with-properties-file-at-compile-time is worth a read –  Feb 15 '17 at 18:53
  • The Eclipse issue is irrelevant other than another reason why we want to get away from running a template file through a Maven filter - that solution locks us into Maven. – Jim Feb 15 '17 at 18:54
  • RC - Thanks for the link. The question you suggest has to do with generating source files from a properties files. That is nearly what we are now doing - using a Maven filter with "properties" defined in a script - that script is responsible for gathering the values and providing them to the compiler (currently C) - the method you suggest would have us creating an additional step, neither of which is our goal. – Jim Feb 15 '17 at 18:59
  • Locked into maven did make me laugh. –  Feb 15 '17 at 19:00
  • Maybe Java's annotation preprocessing can help your use case. – ZhongYu Feb 15 '17 at 19:26
  • ZhongYu - Thank you for your comment, the use of annotations was brought up in our team, and we started looking at that, do you know of a good resource we should be looking at? – Jim Feb 15 '17 at 21:11

2 Answers2

0

The xxx.c file can then use "COMP_ARG" and its value will be embedded in the code and we have little worry about it being changed inadvertently.

...our requirements are such that some information be embedded in the code....

We are looking for a way to specify at compile time various values that are available to the Java code. We are quite aware that Java does not have a pre-processor as does C, so the mechanism would be different.

It seems that the best way to solve this problem would be to make use of annotations in your code.

In Java, annotations are a kind of interface declaration, but they do not enforce a behavioral contract with an implementing class. Rather, they are meant to define a contract with some external framework, preprocessor, or with the compiler itself. Annotations are used extensively in Java EE 5.0 (and later) to specify configuration and behavior to the framework within which the developer's code runs. Annotations are also used extensively by the JavaDoc documentation processor. Here, the annotations in the doc comments allow you to specify and format the information which you intend to appear in the documentation when the JavaDoc processor runs.

Annotations can be defined to be accessible at runtime. In such a case, the primary mechanism for accessing annotations is the Java Reflection facility. For example, annotations with a retention policy of RUNTIME and defined on a class, can be accessed through that class's corresponding Class object:

Class myCls = MyClass.class;   // the "class literal" for MyClass
Annotation[] annotations = myCls.getDeclaredAnnotations();

Annotations can include arguments for parameters to allow for more flexibility in configuration. The use of annotations is most convenient when the code itself can be so annotated.

A quick tutorial on how annotations are defined and used in Java is available here: https://docs.oracle.com/javase/tutorial/java/annotations/

scottb
  • 9,908
  • 3
  • 40
  • 56
  • scottb - Thanks for the reply - I can see how to use runtime annotations to get data, but how do I provide the data values at compile time? – Jim Feb 15 '17 at 23:28
  • Your question mentioned that embedding data in the code was a requirement. Am I understanding that this isn't your goal? I am not aware of an accepted and well-characterized mechanism to dynamically compile information into your code ... Java is a strongly and statically typed language and is not well-suited to this purpose. Of course, it is possible to provide data at run-time to a Java program either via XML or even the command-line, but I suspect that this isn't what you're asking. Such data will not become part of your compiled program. – scottb Feb 15 '17 at 23:45
  • I use the term "data" loosely. The best example I have is something like 'private static final String compilationTime = "xxxxxx";' Where the x's would be replaced by the process or passed in through a constructor to final variables. The concern with XML and properties is those are provided by files and files could be mis-matched with the application. We had the process for C and, as many point out, it is painful to do with Java. I have achieved a measure of success with Maven's filtering, but was looking for a better solution. – Jim Feb 16 '17 at 22:17
  • I know this is not supported, but if I could do this: 'javac -J-Dname-value ...' so that javac adds code to define "name=value" as if it were on the java command line, that would do it. There a many things we can specify at run time, but some need to be baked in. – Jim Feb 16 '17 at 22:28
  • For this case, an alternative would be to define an enum class to contain the data that you would have specified to the C preprocessor. The enum class gets compiled into your program, however, and can only be changed by editing the class and recompiling the program. If your enum class is named `PreprocessorData` then you would use this data in your application as `String myString = PreprocessorData.EnumConstantForThisDirective.getValue();` ... Again, Java was designed to be securely and strongly typed, so it is not designed to do what you did in C. You're going to have to settle some way. – scottb Feb 16 '17 at 23:51
  • scottb - Thanks for the response. Your suggestion is pretty much what we are doing now and wanted to avoid - updating a source file. As for the "securely and strongly typed", I don't see how that is affects what I want to do - runtime data would be no different than receiving any other command line argument or property - I would be validating the input data. – Jim Feb 21 '17 at 14:06
  • *" I don't see how that is affects what I want to do - "* ... you're quite right. I was trying to make the point that Java has no well-established or built-in mechanism for conditional compilation as there is in C. One way to achieve a similar result is to use Ant or Maven, as you have been doing. – scottb Feb 22 '17 at 17:35
  • I see. I was hopeful for some mechanism for code generation (or something) that I had not heard about. In all fairness, Eclipse is the problem with my process, not Java itself. – Jim Feb 23 '17 at 19:43
0

I'm going to post my own answer which seems to be "Can't be done" - what can't be done, apparently, is provide at compile time to Java, a set of parameters that gets passed to the program at execution time. The solution appears to be to continue with what I am doing which is to update a Java source file with the compile-time data and figure out how to coax Eclipse to stop over-writing the files.

Thanks to everyone who commented.

Jim
  • 35
  • 1
  • 10