Getting Started With Programming in Java

Conventions

 

Basics

 

A Basic Path Tutorial

 

There are, essentially, two types of operating system, file management systems available... POSIX, and Windows. Windows uses a backslash ('\'), all others use foreslash ('/').Windows has an additional formatting of type [DRIVE_LETTER:]. That is fairly consistent. Network drives utilize a different naming scheme, however it is consistent for all Windows-Based Resources. That is beyond the scope of this documentation.

if (you have a path-based entity) {...

the java command takes a -cp (classpath) argument.... It may contain... any number of pathSpec elements, each, either relative or absolute.

For Example:

c:\

/

c:\some_dir

c:\some_dir\

/some_dir

/some_dir/

./some_dir/some_file.somefile_extension

/some_dir/some_file.somefile_extension

.\some_dir\some_file.somefile_extension

\some_dir\some_file.somefile_extension

That covers almost all possibilities... You dictate a path...

You may have multiples. It may or may not contain .class files (.jars && classpaths do[at least for mine]), hotswap-agent.properties, for example, does not... Think like application.properties for #Swing.

A Basic ClassPath Tutorial

 

So for example purposes...

If, we included all of those included from the previous section, to run. X.class, no that's not legal, must compile then run...

Windows


javac -cp c:\;c:\some_dir;c:\some_dir\;.\some_dir\some_file.somefile_extension;\some_dir\some_file.somefile_extension; [x:\|[PATHsep][TOsep]CLASS_TO_COMPILE.java                                                                                                            //no parameters required, You Should probably delete this if you are planning to copy/paste code. We make our own.

Mac/Linux


          [Legal on POSIX, ... formatted ok! Separator: OK!]       delimiter is OK!""                         [] [] theSpaceBetween... #DaveMatthews: 
javac -cp /:/some_dir:/some_dir/:./some_dir/some_file.somefile_extension:/some_dir/some_file.somefile_extension: [/][PATHsep][TOsep]CLASS_TO_COMPILE.java                                                                                                                    //no parameters required, You Should probably delete this if you are planning to copy/paste code. We make our own.

For example, let's see how it needs to be formatted?

So for example's sake...

java -cp <target><delimiter><target>/jars/*<delimiter><target>/jars/sub1/*<delimiter><target>/jars/sub2/*<delimiter>etc...

If I understand correctly, it should end with a delimiter?

Yes, that is correct..., at least, until we override...

Environment

To begin working with Java, we need a Java Development Kit. The options for which manufacturer, what version to run, as well as what version to compile with or to, are many. To use Hotswap Agent, we need to install the Java Development Kit by Digital Code Evolution, as well as the HotSwap jar for the version we will run. Some of the older code (particularly 0.2.0) used the Hotswap Agent, but I have mostly stuck to just manual restarts to ensure a fresh copy of the code is run. Because I rely heavily on the SystemCompiler utility, my code is somewhere near the latest version, compiled (generally) to the lowest compatible, in the current case (tecreations-0.3.0), Java version 8 (class version 52.0).

Unpacking and Making Projects

You can always unpack and build a project using WinRar or your favorite Zip utility as .jar files are an extension of .zip files. Just unpack to a directory and build/compile.

All the tecreations* packages include source, binaries and dependency jars. You may use Launcher (discussed below) to operate on a .jar or class path to effect operable code. You may need to compile, as well, depending on your JDK version. Newer JDK versions will run older code, however the inverse is not true, newer version compiled code will need to be recompiled for older JDK versions.

ProjectPath and setProjectDir()

In a nutshell, Java uses a setting called a "classpath". This consists of a path and a directory ie: c:\[java_dir] or /[java_dir], a jar file, a combination thereof, as well as other possible entries, with each entry being a path, ie: path[sep] + 'some_dir' + sep + 'maybe_another' + sep] + ['file.extension'].]. So a classpath contains multiple path entries, some may be relative while others may be absolute. The classpath also supports the '*' wildcard (including all files). Anything referenced on the class path (particularly .class files), are attempted to be loaded, or are otherwise available to an application. There is some clarification on using System.getProperty("java.class.path") here. Furthermore, one must understand classPathSpec delimiters where classPathSpec is some member of the list of items on a classpath. They should be delimited following this rule (java code):

(File.separator.equals("/")) ? ":" : ";"; // win == ';', mac/linux == ':'

In essence, I strive to keep all my projects in my Documents directory as this makes them relatively easily available from a coding persepective. In this way, they are contained in a central location. As always, the definitive authority on the topic is the code itself, as it does not lie, however, sometimes comments do. I try to write my code in a certain way, which should be easy to understand and test, helping you to write better code.

ProjectPath.setProjectDir("simple_name") configures ProjectPath for a specific project name. ProjectPath is the source for most path elements. There is also some code in Jar/JarReader related to the /tecreations/jars/ paths (for unpacking dependencies in), but those parts will probably be migrated to ProjectPath over time.

Bootstrapping Building

With the previous sections in mind, let's look at rolling back to a previous version. The tecreations-core-1.0 package was compiled using DCEVM-11. In order to use this code with a previous version of the JDK, we must recompile as we will get Invalid Class Version errors.

Consider the following examples:

Clean projectDir ca\tecreations of all .class files, compile <defaultpackage>\Build, and run.tecreations-core-1.0

I'm running JDK9 at present, so this package is now in that version. If I wanted to use JDK 8, I'd have to recompile to go backwards in versions. We could also change the code in BuildProject.java to inlude '--release 8' in the list of arguments to javac, but compiling it to the current JDK version also works to make the code translatable. If you are using a JDK >= 11, you probably won't have to recompile.

Also note that the tecreations-core-1.0 package DOES NOT support a --release version. tecreations-0.3.0 and above do.

If you want to build another package, you would use the same commands with a different target. If attempting to build a package that was compiled with a later version of the JDK, you will probably need to Clean as well, which deletes all .class files within a package.

Your best source of information on how this code works is to first read the code and if you still have questions, then email me. My email is at the bottom of this page or on the Contact page.

We only have to remove the .class files if compiling to an older version due to the classloader loading the compiled sources, in this case, resulting in Invalid Class Version errors.

I've tried to make it as easy as possible, however, that's sometimes difficult to achieve.

For version 0.3.0, I did this...

Clean projectDir ca\tecreations of all .class files, compile <defaultpackage>\Build, and run.tecreations-0.3.0

Now in this example, you can see that I used the default package's Build class. We edit and compile .java files (editor + javac [or in our case, Build and SystemCompiler]), and we execute .class'es (java [or in our case, Launcher]).

Also, it recommended that you use the latest version of the tecreations* packages. I am constantly modifying the code tecreations-x.x.x package. It started with tecreations-core-1.0 and has been refactored to 0.2.0 and on.

SystemCompiler

With SystemCompiler, we can select a bunch of projectDir's and compile-on-save. Therefore, when we call code that we have dependended on, the current version typically runs. We do run into problems with Class Version Errors, that just means we have to compile again, typically from change of JDK version.

The SystemCompiler can AutoRunOnStartup (if ran as an Administrator), for Windows. Mac and Linux, you must build your own OnStart functionality. There should be a DebugPrint version and an AutoRemove function that removes it from the startup process.

The SystemCompiler, on Windows, has three output windows -- Paths (displays monitored paths), Output (displays javac compiler output: errors, warnings, etc.), and Status (displays the most recently compiled class Simple Name [ie 'SystemCompiler' when class is equal to 'ca.tecreations.SystemCompiler']).

Output should only display text when there is an error (I forget, maybe on warnings too) output, and Status only shows the next name (it should be: if and only if), the class is compiled, irrespective of warnings, errors and compiler bugs, but that's not real. It prints it out anyway.

Running Applications

ca.tecreations.launcher.Launcher

So for a self-referencing jar, I did this...

run-tec-0.3.0.Package

 

java -jar tecreations-0.3.0.jar will launch the tecreations-0.3.0.jar, if it's in your current directory.

From this app, I can load classes and dependencies for execution, whether in a jar or class path.

There is some headless selection handling, however, if I remember correctly, you must specify the target as the first parameter to the .jar or class (ca.tecreations.launcher.Launcher), because of how the code operates, does that make sense? You may need to change the code and, if so, good luck. Test frequently.

For jars, any dependency jars placed in the /jars/* directory structure will be unpacked, if not already, into <user.home>/Documents/tecreations/jars/<jar_simple_name>/jars/

To force re-unpacking, for example after changing dependencies, simply delete the appropriate /jars/ directory in the tecreations directory. Note that the tecreations directory is a special path I use internally for a variety of purposes, mostly properties, holding jars for jar dependencies and some static data files. Likewise, with .properties files, you may delete any of them and the appropriate class will re-generate the defaults.

ca.tecreations.launcher.CommandLauncher

For testing multiple operating system commands, I'll often use the CommandLauncher. It lets me execute an operating system command, optionally save the command to the properties between executions and replay them.

ca.tecreations.launcher.Relauncher

For launching classes with a set of dependency jars, as we've discussed, there is the Launcher. For instances where the Launcher is ineffective, there is also Relauncher.

Relauncher will 're-launch' a class, with the classpath constructed of <target><delimiter><delimited_jars_in_projectDir_jars_subpath>.

As always, check the code, but if I remember correctly: java -cp tecreations-0.3.0.jar ca.tecreations.launcher.RelaunchJar <target> [args].

Relauncher determines the target type (projectDir, classpath, or .jar) and launches either RelaunchJar or RelaunchProject, as appropriate.

The dependencies and refreshing them are an ongoing issue. We are trying to work it out, but it is, at present, an unsuitable solution.

Dependencies

ca.tecreations.pomdeps.DependencyViewer

I've been using a modified pom.xml system utilizing Eclipse Aether and Maven Resolver via Java code (programmatically). The result is DependencyViewer.

This class houses a JTree for displaying the transitive dependencies for an application, as resolved by Maven Resolver using a custom tec.xml file. Its' format is similiar to a Maven pom.xml file, except that it only retrieves the transitive dependencies for the artifacts entered in the <dependencies> section.

This should allow you to use a pom.xml file as a source for the dependencies, and upon saving the text, the application will resolve and download the dependency .jars. It used to use the <dependenciesManagement> section and list those also, but it appears that I have removed that functionality. (Probably due to too many failures.)

Currently, it downloads and creates a repository in C:\temp\, but that can, of course, be altered. That's one of the benefits of using this code, complete freedom.

After completing the resolving and downloading, the application ouputs "Action done." You may then commit the dependencies to a /jars/ directory, with or without emptying it first. I usually need to empty, but sometimes, if I'm just adding a dependency, I'll simply commit the new set to the /jars/ directory.

The application will output "Action done." after copying the committed jars.

It should be noted that for Spring projects, I'm able to easily add the dependencies and it works. There have been instances where it wouldn't and in every case I found it was something I was doing wrong that caused the failure.

In case you haven't understood how the /jars/ directory works with the tecreations* packages, /jars/ is a special directory. Any .jar files placed in this directory will be entered on the class path argument when Launch'ing or Relaunch'ing. CommandLauncher only works with shell commands, so it doesn't construct a classpath, you must do it manually for that. Nevertheless, in Launcher and Relauncher, we construct the -cp argument, using the source classPath/jarPath and the contents of the jars directory (relevant to the target, jars use tecreations/jars/simplename/jars/). Note that you may also break up your /jars/ directory into /jars/path1 /jars/path2, etc. The manner in which the class path argument is formed is using /path/*<delimiter> elements, therefore, the classpath is kept as short as possible to facilitate debugging.

Submitting Feedback

So, I have a dedicated email for the server, tim@tecreations.ca. You may send email to this account and I should receive it at least every day or two, so I can respond relatively quickly if you have questions, suggestions, a problem report, feature request, or you just need to reach out.

Good luck!

Also, don't forget to check back now and then. I'll keep producing (hopefully) good quality code, so maybe there's something you can use.