I have build a set of Java classes that act as kind of plugins in a third party application.
When ever new request come on my table I create new classes (plugins) or modify existing one.
To make the changes available to the third party application I can put a Jar into an so called extlib directory or put single class files into an so called ext directory.
I am looking for a proper way to handle different versions of my files.
When changing only one single class it a bad idea to replace all class files in ext dir. Same problem when compiling as JAR. After changing one single class, I would have to compile q whole new JAR with all files inside.
Replacing all files inherits the chance of accidentely replacing a untested change.
Do you have any hints / best practices of how I could manage the different file versions?
My Ideas:
Some kind of patch would be great. When changing some files, I just push a button to compile a zip archive with all changed files inside. In optimal case with a version mark in all the files.
Would something like this be possible with eclipse plugins pxe.?
There exist a number of workflows for this.
The terminology varies a bit depending on the version control system that you are using; I am going to use git terminology.
One workflow is to always work on a branch, and to never merge a branch that has not been thoroughly tested into master. So, then, a release is only made from master.
Another workflow is to work on whatever branch you want, merge into master whenever you want, then every once in a while pull from master into a designated "release" workspace, do your testing there, and then release from that.
As for binary patching, I am sure there exist tools out there, but I do not know of one, I asked a few people and they don't know either, so I have no answer for you here. I suppose if you have .class files you can use some folder synchronization tool, but if you have .jar files then you are going to be replacing them in their entirety.
Related
After developing a java app in Eclipse, I would like to deploy it by packaging it into a runnable .jar with only the minimum necessary by the main method and its dependencies.
I have several packages in my workspace I work with too, but do not need to be in the resulting .jar file.
When I try to export, it clearly says that the required libs will be there, but also the other independent packages are inside too. (With the Export option happen exactly the same)
I choose to export only the Main class of the com.project... package, but also the test.project... has been packaged.
In the project I have both com... and test... packages obviously.
How could I force it to truly package only the required ones?
Thanks in advance.
TEMPORARY ANSWER (2019-07-03):
Seems that, for now, there is no way to achieve this automatically, thus the answer from #arnonuem seems a good workaround.
If better news, please feel free to improve this thread.
Thank you all.
I would create an ANT file for this specific task. There you can freely customize which packages should be compiled into the jar and which not.
Please inspire yourself reading this example.
For a general overview what i am talking about you could take a quick look into this.
https://howtodoinjava.com/ant/ant-build-jar-file-example/
Please focus on
<javac srcdir="${src.dir}" destdir="${build.dir}" classpathref="classpath"
includes="src/path/to/TheClassToBeIncluded.java" />
For more detailed information on how to include or exclude files or packages you should refer to the documentation over here:
https://ant.apache.org/manual/Tasks/javac.html
At the bottom of this page there is a list with valid build parameters.
First of all, we have to distinguish build and export.
Build transfers .java source code into .class byte code and mostly copies other resources. While doing that it usually merges all source folders into a single bin folder.
Export runs a build (or relies on Build Automatically) and then modifies the resulting .class files and other resources. Usually it packages them into one or more .jar files.
Therefore, our solution includes two steps:
build everything that is unwanted for export into a separate folder (or more)
export from a specific folder (or more)
For step 1, refer to this answer on Stack Overflow.
In a nutshell: Go to Project Properties > Java Build Path > Source tab > Allow output folder for source folders. This enables you to configure a specific output folder for each source folder in the centered viewer.
For step 2, we need to understand that eclipse's Runnable Jar File Export relies on a Launch Configuration.
So before exporting, go to Run > Run Configurations..., select the Classpath tab, remove the default User Entries and hit Advanced.... Now you can Add Folders containing your built classes.
You might want to use separate Run Configurations for internal testing and exporting.
I have struggled with this problem on and off for years, supposing it was just me who was failing to find the right solution. Possible solutions always seem to involve detailed manual configuration e.g. configuration of the build path, or selection of the folders from which classes are exported into a jar, or learning ant, but which still requires manual configuration. The problem is that the inter-dependencies between classes (and packages) are complex - imagine drawing a network diagram from import statements. Manual configuration is time-consuming, error-prone and, I think, infeasible except in simple cases. I am a bit stunned. If there is no automatic solution for selecting necessary classes, I suppose people are regularly exporting their entire code base and that the world is full of bloated jars ... (and, incidentally, without obfuscation, the entire source code base is thereby made available through reverse engineering).
We all know "inputable" resources are by convention in src/main/resources and src/test/resources, but what about the runtime outputted ones? Is it better to use target/ or target/{classes,test-classes}or simply give up and try to use external path even if it complicates things for security reasons? I've been brainstorming a bit regarding that decission as shown following, but need the help of more experienced users that can shed more light.
PROS of target/{classes, test-classes}
If maven engineers architected the convention by moving resources to target/classes instead of target/resources I assume they had a good reason in mind for preferring it
It organizes input and output resources on the same base folder
It makes test and main outputs independent, so no conflict can appear if names are equal
IT makes much conventional and secure to define the relative route of the resource ( by ClassLoadeR().getResource() or etProtectionDomain().getCodeSource().getLocation() [no file globs]
It makes much easy to centralize output behavior, in case our idea is having a function for UPSERTing resources, we need to use resolution for sufolder as they are not in the same path (so prepend /classes/ to the relative route but / for an original resource)
I think due to the previous ones, there can be a bit of confusion when using parent poms, because there is a target for both parent and module, but only one classloader URL -> /target/classes
It works flawlessly if using the classes directory as the base classpath of the app, when executing directly from console.
PROS of target/
When packaging the app as a library, you don't need to deal with an output folder inside the jar.
I have been told that maven doesn't like too much anything strictly outside of target/, but have no further info
A central folder can be used when executing tests in case production code generates files and tests works with them also
Perhaps a single target at parnet pom's level makes files easier to share among different modules
So how do you usually handle these sort if things?
I am sure some of you have a more authoritative question
So typically if you are allowing resources to be pulled in from outside of your Jar you need to either hard-code that relative path or read it from fixed config file. You would then document this when you release your application.
For example, Eclipse has a folder specially for plugins. You can drop new plugins here and know that Eclipse will pick them up and know what to do with them.
In my applications, I usually define a conf directory that sits at the same level as the executable Jar. I'll put any log4j and other such post-compile config files there.
You mention security issues, which is a good thing to think about. When you are pulling in data, always try to do some sort of sanity checking (make sure a directory exists, a zip file isn't corrupt, etc). Since you can't control what comes in, make sure you do as many checks as you can on the program side.
I am using Eclipse Juno with Subversive plugin.
I have a java project set to compile automatically which creates a lot of bin dirs
No matter what pattern i put in window-> preferences->->team->ignored resources, eventually i see the bin dir and all of it's sub dirs in the team synchronizing perspective as new uncommitted files.
I have tried the following syntax:
*/bin,**/bin, */bin/, */bin/*
No luck.
Also, I have noticed that sometimes if I close eclipse and start it again, the ignored files disappear from the team synchronizing perspective as required, but still, some bin dirs are still present. This whole thing is very inconsistent.
Any idea ?
I have forgot to mention that I am using two worksets, one is the subset of the other, this add buggyness to the whole process appearently
Try the "Subversive SVN JDT Ingnore Extensions". It is located on the Juno Update Site, under "Collaboration". Its description says:
The feature is useful for Java development because it allows to automatically interpret output folders as ignored resources.
Seems like exactly what you want. Also, it should work independently of the name of your output folders which is an advantage if you use Maven for example (in that case, your output folders will probably be called target and not bin).
I gave up and switched to Subclipse. Now everything seems to be working fine, or at least less buggy.
We have an java application in which the user can write/execute their own java code and use imports from compiled jars - i.e. they write it, and it is compiled and run by the application. They can also save this code (along with various other information that they are using) - currently this is saved to a human-readable xml file.
I want to be able to use those save xml files in an IDE (principally, Intellij), so that if the user changes things in their compiled jar in the IDE, these changes can also be picked up in the save xml file.
For example, if a save file used a class from the compiled jar, it may have the following import:
import com.company.project.package.subpackage.MyClass;
Let's say that class was moved, so the import was:
import com.company.project.package.subpackage.subsub.MyClass;
...this would change all the save xml files that used that class and import - just as the IDE would for all the other usages in the compiled project.
(This, and other examples, arises because the compiled jar is both constantly in development and in use using the aforementioned application.)
At the moment, if I were to add the save xml files to a sub-project in the IDE, the user can edit the save files manually, possibly taking advantage of 'find/replace' or 'search for usage in text' functions. This is better than nothing, but still a rather involved/complicated process. Also, there is no checking that the code in the save files are consistent with the code in the compiled project.
One approach that I am considering is a script or a test class that would unpack the save xml file, writing the java code to java files, and then try and compile (and possibly running/testing) those java files.
A further step would be to write a maven plugin (we use maven for our build cycle) or an ant script (ant still has its uses...) to do this, and possibly make this part of our build process - i.e. you cannot compile the project without ensuring all of the save xml files in its sub-project also compile.
Does this seem like a reasonable approach?
Are there alternative approaches that anyone could suggest?
..saving as a .java file is not the solution I'm looking for.
Save it as a Zip with 1 (or more) XML files as well as any source (in paths according to package) that is required. You could even include other files easily, a manifest, help files etc.
This has a number of advantages:
It allows source & include files to be a different encoding to the XML
It consolidates all the necessary parts of the project into one file, without any 'jumping though hoops' to make one format fit inside another.
It allows different compression levels as appropriate to the data (e.g. text/XML compresses well, whereas a serialized image does not).
How do I clean up stale .class files out of ${workdir} given set of existing .java files in ${srcdir}? By stale I mean .class files that were generated from now removed .java files. I have tried coming up with something using Ant mappers and filesets etc. but I failed. Removing all .class files older than their respective source .java files would be acceptable, too.
I'm pretty sure there's an ant task to kill .classes older than the .java...
Depend sounds close, and may actually do what you want, but this isn't its intended purpose. Given developmentalinsanity's answer however, this may be the only thing that will Actually Work.
The problem is determining whether a class file without an obviously corresponding source file is really stale.
Try this in a single file (A.java)
public class A{}
class B{}
This will result in both A.class and B.class. So, B.class would seem stale because of the missing java file. You'd probably get similar issues with any inner classes.
Safest bet if you want to make sure there's no old class files lying around would be just to delete them all.
As it’s just not possible to detect what’s stale and what’s not, most builds have a clean target (that’s also part of cleanbuild). The clean target, just removes all files from you’re build directory. This directory normally is unversioned (svn:ignore).
Not all files in you’re build will be the result of the compiler, for example .property files, these files can be stored in an alternative directory that will be copies in to the build directory. For example in a web application build you can store those files in /web/WEB-INF/classes and let Ant copy them into the build directory.