How to properly organize and nest packages in Java - java

Going by the Java Tutorial for package naming convention if I were to use the following approach:
org.example.hyphenated_name.user
org.example.hyphenated_name.product
How would this translate to actually creating this package structure. Would I create a separate package for org then within org would i create example and so on or would it just be 2 packages org.example.hyphenated_name.user and org.example.hyphenated_name.product
Basically what I'm wondering is if the . is just used for naming separation or if it's used to mean physically creating a new package each time.

This is how it looks physically on a disk drive:
$ mkdir -p org/example/hyphenated/name/user
$ mkdir -p org/example/hyphenated/name/product
$ tree org
org
└── example
└── hyphenated
└── name
├── product
└── user
5 directories, 0 files
So actually, you have a structure of packages:
org
org.example
org.example.hyphenated
org.example.hyphenated.name
org.example.hyphenated.name.product
org.example.hyphenated.name.user
By creating such a structure, you can now use each package for a different action. Product-specific action classes in org.example.hyphenated.name.product and user-specific in org.example.hyphenated.name.user package. This way you can as well put classes that use both of these packages in e.g. org.example.hyphenated package. This way you create a well-build application structure that is easier for other people (and for you in 2-3 months) to read.
EDIT:
Normally you won't need to care about creating folders for packages, because your IDE should take care of this instead of you.

A package isn't a "thing" that you have to create (except that you normally have to create the directory hierarchy for storing the source files). You pretty much just say that your class belongs to some package, and the compiler says "OK, whatever you want". There's no built-in relationship between package_a.package_b and package_a.package_b.package_c that has any effect on language semantics. (What I mean here is that if you have a class in package_a.package_b.package.c, then within that class there is nothing special about classes in package_a.package_b as opposed to, say, package_z.package_y. In both cases, it's just "some other package".)

Related

What's the point of a deep folder structure in Java (Maven)?

I've inherited a Java (Maven) project at work. I'm not a Java developer, but the project is now mine, nonetheless. When I clone (a la git clone) the repository, I notice the folder structure goes really deep before any .java files appear. For instance, the folder structure looks like this:
project_name
.git
.idea
src/
main/
java/
org/
bah/
co/
lab/
zeus/
apimanager/
RestClient.java
I've googled around, trying to find out why the folder structure goes so deep. After some research into Maven, my understanding is the default structure begins with /src/main/java. So, I'm curious why the previous (now incommunicado) developer structured this repo (and many others) like this. So as not to solicit opinion, please tell me: is there a technical reason the project is structured like this? There are literally no other .java files outside of the apimanager folder, so what technical reason would there be to bury everything so deep?
Maven is a tool that has certain opinions on where things should go; a default configuration. You don't have to follow it, but not following this default configuration has three significant downsides:
You do have to then configure maven to tell it about the alternative choices you made. Maven does not make this easy.
Other java programmers generally assume the defaults. If you have a good reason to deviate, go for it, but 'I do not like it' is not a good reason, as it'll be pointlessly increasing the learning curve.
The maven developers chose this structure as default for a reason. If you think it's a dumb reason, that's certainly possible and you may even be right, but then you're using a build tool written by folks who, (judging the book by its cover a little bit), according to you, make boneheaded choices about sane defaults. That's not a great place to be.
To explain each layer:
src
Indicates that these are source files: Compiled and generated stuff should not be in here, and the entire src tree should be in version control. Contrast to e.g. bin or build containing build artefacts, doc containing documentation, and who knows what other directories you need for other relevant parts of a repo.
main
A project can consist of multiple separately buildable artefacts and 'kinds' of product. For example, most projects include a bunch of code that exists solely for testing purposes (the unit tests). They live in src/test. The core product lives in main.
You can also have for example separate sources for an installer perhaps (src/installer), or a build plugin, or an annotation processor that needs to be built first and then it needs to be on classpath when compiling the main project, etcetera.
java
There's such a thing as split language projects, where some of it is written in language A and some of it in language B. For its worth, I think this layer is bad design; A file ending in .java gives away how one is to 'compile it', and this goes for just about every source file that needs a compiler applied to it: The extension says just as much as a folder name of java ever could. To show you a common contrast: Many projects have src/main/resources as well as src/main/java: Resources are 'compiled' simply by copying them over: Imagine your app has a text file containing a list of all US states with all zipcodes used in each state. Or png files with icon images for a GUI app. Such files are just as much part of your main application as the class files would be and should end up in the same place (inside the jar file), but to 'compile' them, you just.. copy em, you don't run javac to do this. That's what this level is about: What tool should be used to turn source files into distributable aspects?
co/lab/zeus/apimanager
This matches the java package structure. This is effectively a requirement applied by javac itself. The reason to use such a deeply nested package structure is simply because packages serve as namespaces: If there is a conflicting fully qualified name, all hell breaks loose: Java simply cannot handle this. Hence, java programmers ensure that such conflicts never happen by using a 'reverse domain name' structure: You'd stick your project in that package if you own the zeus.lab.co domain, thus ensuring nobody except other folks in your team who share control of that server could possibly be in conflict (and for those: They're in your team, talk to them to avoid conflict). For example, there are 3 different open source java projects all called spark. Had they all gone with package spark; (and thus, src/main/java/spark/Main.java as an example file), then for every java project you'd pick one of the 3: The other 2 you can never use in this project. Harsh, and pointless, which is why (almost) all java libraries use a reversed domain name as root package name, and then maven follows this package name in its directory structure because javac makes life extremely difficult if you don't do that.
That gets us to project_name/src/main/java.
org/bah
You made that up for hyperbole. Nobody hosts a proj on zeus.lab.co.bah.org. But if they do: Talk to the management that decided to assign that whopper of a domain name to a team. It's on them, not on the author of this project.
Maven is a build and dependency management tool that helps develop your application and manage all the lifecycle of your development process such as build, compilation, packaging, testing, etc. through command lines.
There is a convention on how a Maven project is structured:
└───maven-project
├───pom.xml
├───README.txt
├───NOTICE.txt
├───LICENSE.txt
└───src
├───main
│ ├───java
│ ├───resources
│ ├───filters
│ └───webapp
├───test
│ ├───java
│ ├───resources
│ └───filters
├───it
├───site
└───assembly
What is important to understand for the moment is the role a each files and folder and how to use Maven commands.
pom.xml : this file contains the structure and the information of your project, and your dependencies (external jars). This file is used by the commands you execute in Maven
src/main/java : contains your packages and your source code.
src/test/java : contains your test code
In your case, the structure of your project is due to the package name. Here, the name is org.bah.co.lab.zeus.apimanager and in Java a package is physically a nested group of folders. There is a package naming convention, but in most of the cases, it is up to you to choose the name you want to use.
As you are using IntelliJ IDEA, you can display your package with the options Compact Middle Packages.

Packages different than file system paths in Java (and Android)

I am building an SDK in Java that has a public API and lots of internal 'private' classes. I would like to keep the public classes as public, but restrict the visibility of all the internals. I have to stick to Java 8, so I can't really take advantage of modularity introduced in later Java versions. We all know that in Java (unfortunately) packages are not really hierarchical - for example com.test1.test2 package is not really a sub-package of com.test1 and thus any class declared with package visibility modifier inside com.test1.test2 will not be visible from class declared inside com.test1. I can't really simply put all the classes in a single directory as that would make working with the project a nightmare.
I was wondering if it's possible to keep the file system hierarchy as usual, but declare classes as if they were inside a single package. For example create 2 files like these:
Class1 under path com/test1/test2/Class1.java
package com.test1;
class Class1 {}
Class2 under path com/test1/Class2.java
package com.test1;
class Class2 {}
So that logically, both of these classes would end up under the same package and be accessible from within one another using package visibility modifiers.
I know this is highly unusual and probably not supported by many IDEs, but I gave it a try using plain old javac and as long as I specify each source file by it's full path it compiles and runs just fine. Do you see any technical problems with that, other than (obviously) breaking the 'good practices'. If it makes any difference it is an Android project but written in Java.
If you want to keep two .java source files in separate directories, but having the Java classes belong to the same package, then you need multiple source root directories.
This is e.g. how test code is kept separate from regular code in a standard Maven project.
So, create the files as follows:
src1/com/test1/Class1.java
src2/com/test1/Class2.java
When compiling, have both src1 and src2 on the source path. Since the source path by default is the same as the classpath, that means using e.g. javac -cp src1;src2 -d bin com/test1/Class1.java, which will correctly find and compile Class2 if it is used by Class1. All the compiled .class files are consolidated in the single destination directory (bin in this example).
Having multiple source roots is common (all Maven projects have them, by default), so it is fully supported by IDEs.

How can I determine the org of a given jar and the names of contained packages?

I want to use some of the java classes contained in a jar, say introcs.jar for example. As seen in Java code to import JAR file, one needs the values of org and somepackage to import. If I only have the jar (without any other info.), how can I determine org a somepackage? I prefer not to unpack the jar if possible.
It's trivial if org and somepackage are known. I know how to add to the classpath.
(Windows 10 x64)
The linked page shows that the classes are all in the top-level package which has no name. Also, it looks like these classes are meant to be run, not imported. To run them, type:
java -jar introcs.jar <ClassName>
In general, though, any decent jar file should come with documentation saying which package each jar is in. You basically need to know some things about the class you're going to use; at least, what the class does, and how it should be used. And an essential part of "how it should be used" is which package it's in.

Can I create folder inside package in eclipse?

I have project, with source folder "app", inside this package I have package "models". Can I create folder or any other kind of subdirectory within this package? So that eventually I would have something like
-app
-models
-Folder1
-file1
-file2
-Folder2
-file3
-file4
When I try to force creating folder inside (by clicking new->other->folder), I cannot add anything to it.
Creating a folder within a package simply creates a new package
e.g. The folder structure
- app
- models
equates to package app.models
Adding a new folder, Folder1 to this structure
e.g.
-app
-models
-Folder1
equates to the package app.models.Folder1
a folder in a package is just another package, so you want new->package then type in app.models.folder1
Packages and folders are slightly different conceptually.
You generally group your classes that deal with the same functionality in the same package. For example the core classes, the model of your app can be in com.example.myapp.core and the ui classes in com.example.myapp.ui .These packages are represented on the disk by a folder structure.
In my opinion, you should not change this package structure to add files that are not Java classes. I would suggest to add a resources folder at the top of your app tree so that your data and your classes are separated.
But if you want to just add subpackage, do not create a new folder, just create a new package such as app.models.Folder1.file1 and you will get the structure you want.
You can refer to this question to know more about the packaging conventions: Are there best practices for (Java) package organisation?
The default package representation is Flat. You want to change it to Hierarchical.

In Java, should I be creating a new Package, Folder, or Source Folder?

There are a couple of questions on SO that sort of hit this, but I am totally new to Java development and I don't know the correct way to approach this.
I have a C# solution, containing two projects (my app, and a unit test project) and within the app, most things are put into folders eg. Interfaces, Exceptions etc.
I am trying to recreate this in Java / Eclipse, but I don't know how. I ended up with lots of packages, which sounds really bad. I also tried adding a source folder but that ended up being outside of the package.
Could anyone point me in the right direction?
Namely, which of those should I use to represent my unit test project/set of unit tests, and subfolders which exist just for organising stuff.
Edit: It also says use of the default package is not advised. What should I be doing?
Edit 2: Here is what it looks like. Does this look vaguely correct? My original C# solution is on the right.
In a typical java eclipse project, you will have one or more source folders (for example one for app code, one for your unit tests).
Each folder contains a package tree, typically starting with your base package, for example com.mycompany.myapp.
In order to avoid name collisions, packages names are usually start with the domain name of the entity who is the author of the code, starting with the top-level-domain and going backwards (more general to more specific). That way, each class fully qualified name is unique. For example if google creates a class named List, it will be known as com.google.List, and it will not enter in conflict with the existing java.util.List interface.
You can have a unlimited number of packages inside this base package, for example :
com.mycompany.myapp.persistence
com.mycompany.myapp.domain
com.mycompany.myapp.services
com.mycompany.myapp.web
It all depends on your project and the way you want to organize your code and your classes.
At the logical level, packages are named with dots as separator. They contain java classes.
At the physical on disk level, each package is a directory. The java classes are contained in .java files (most frequently one class per file).
In Eclipse a "source folder" is a folder inside your project that is known to Eclipse to contain java source files. It will be compiled included in the output (for example JAR file) when you build your project.
In Eclipse, you usually view them at the logical level, showing packages. When you tell Eclipse to "create a new package", it will create the directory for you. For example, if you tell it to create the com.mycompany.myproject package, it will automatically create a com folder containing a mycompany folder containing a myproject folder.
In java source tree structure must match package structure
so foo.bar package must be laid out in
src/foo/bar
Also default package may not be advised - but you can still use it - better to put things in a package though
In java different project development structure are flowed according to type of project.
So as you are new to java and Eclipse so it's better to install maven plugin and create maven project and choose a archetypes according to your project type like a standalone or web based.
The maven plugin will create the project structure including packages,test packages source folder etc. You can get more about project structure from this
Using the default package may create namespace collisions. Imagine you're creating a library which contains a MyClass class. Someone uses your library in his project and also has a MyClass class in his default package. What should the compiler do? Package in Java is actually a namespace which fully identifies your project. So it's important to not use the default package in the real world projects.

Categories