I recently started using Eclipse IDE and have read at a number of places that one shouldn't use the default(src) package and create new packages.
I just wanted to know the reason behind 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.
Originally, it was intended as a means to ensure there were no clashes between different pieces of Java code.
Because Java was meant to be run anywhere, and over the net (meaning it might pick up bits from Sun, IBM or even Joe Bloggs and the Dodgy Software Company Pty Ltd), the fact that I owned paxdiablo.com (I don't actually but let's pretend I do for the sake of this answer) meant that it would be safe to call all my code com.paxdiablo.blah.blah.blah and that wouldn't interfere with anyone else, unless they were mentally deficient in some way and used my namespace :-)
From chapter 7, "Packages", of the Java Language Spec:
Programs are organized as sets of packages. Each package has its own set of names for types, which helps to prevent name conflicts.
I actually usually start by using the default package and only move it into a real package (something fairly easy to do with the Eclipse IDE) if it survives long enough to be released to the wild.
Java uses the package as a way to differentiate between classes. By using packages, you can have an org.example.Something class and an org.example.extended.Something class and be able to differentiate between them even though they are both named Something. Since their packages are different, you can use them both in the same project.
By declaring a package you define your own namespace (for classes). This way if you have two identical classes using a different package name (namespace) will differentiate between which one you want to use.
The main reasons I can think of are:
It keeps things organised, which will help you (and others!) know where to look for classes/functionality.
You can define classes with the same name if they are in different packages.
Classes/etc in the default package cannot be imported into named packages. This means that in order to use your classes, other people will have to put all their classes in the default package too. This exacerbates the problems which reasons 1 & 2 solve.
From a java point of view, there are two general dev/deploy lifecycles you can folllow, either using ant to build and deploy, or the maven lifecycle. Both of these lifecycles look for source code and resources in local directories, and in the case of maven, in defined repositories, either locally or on the net.
The point is, when you set up a project, for development and eventually deployment, you want to build a project structure that is portable, and not dependent on the IDE, ie. your project can be built and deployed using either of your build environments. If you use a heavy dependence on the Eclipse framework for providing class variables, compile paths, etc.. you may run into the problem that your project will only build and deploy using that configurationj, and it may not be portable to another developers environment, so to speak.
Related
I have written a common class which I want to use in separate Blackberry applications. This class is not in a separate project but just at a common location and I have linked the path of the common class in Java Build Path. I have added same common path to both of my BB applications and they builds and installs without any problem. When I run one application, it start running but when I run the other application, it gives error message "class xxx multiply defined" error and exits.
Any idea what is going wrong here. Thanks in advance
Regards,
Braj
BlackBerry doesn't work as other Java platforms. In BB Java, you can't have two classes with the same full qualified name, even if they live in different projects.
You'll have to rename one of them (either change the class name or the package name) for it to work.
In fact, the only platform where I have seen this restriction is BB. It is a real pain in the ass since you can't reuse a jar library in different projects without renaming it.
UPDATE:
This is the official article on the topic:
http://supportforums.blackberry.com/t5/Java-Development/Application-throws-quot-multiply-defined-quot-error-at-start-up/ta-p/501498
All applications in RIM OS run under one instance of Java Virtual Machine. And therefore it is allowed only one class with particular full qualified name. Adding another class with the same name will lead to failure upon running both of these classes.
There is a library thing, supported in RIM OS, but I do not recommend to use libraries in your project, unless it is very necessary.
It is because if you have several apps with the same library, but with different versions of libraries you may get the same error you reported in your question. And it is hard to manage libraries when you have many applications which use these libraries.
I recommend to copy source code of your library to the project you are working on. Copy via refactoring, to change all full qualified names of classes included in that library.
Thanks guys for replying. I have created a common library and put common code in that. Now I can use this library in different applications without any problem.
However, when I install my applications using BB desktop Manager, the library appears as part of first application but not in second application. I assume it is because, second application realizes that the library is already been included so doesn't need to include it again.
It is time to sub-divide a platform I'm developing and I'm looking for advice on how to handle cross-component dependencies. I spose there a many cases, so I'll give an example.
I have an Address class that I want to make visible to developers. It is also referenced by classes in my.Contacts, my.Appointments, and my.Location packages - each of which I want to be separately compiled, jar-d, and delivered. Of course I want Address to be a single class - an Address works across these platform components transparently.
How should Address be packaged, built, and delivered?
Thanks!
Two thoughts:
Address sounds like a common component that can be used in different deliverables and so should be available in some common or core library
It may make sense for your components to talk to an Address interface, and the implementation can be provided separately (e.g. provide an Address interface and an AddressImpl implementation). This will reduce the amount of binding between the core library and the library your developers will develop.
In this case Address is a part of a library which deserves its own jar. If you create a class named Address in my.Contacts, my.Appointments, and my.Location and you want to use all theses jar in a same application, you'll have a conflict for your Address class.
I suggest you don't "Deliver" these jars separately. Java has very subtle versioning issues that you don't want to run into. Build everything together and package it into one or two jars and always deliver both jars, or build them together and deliver a subset of jars (but never combine new and old jars--don't just try to send a single jar as an update).
If you must build them separately be very aware that final constants are compiled in and not referenced--so if you change one and deliver a new jar, any references from an older jar will not be updated.
Also method signatures that change will have strange, unpredictable results.
It sounds like you want a developer interface as well--that may be a set of interfaces and classes that reside in a separate jar. If you make that one jar well enough that you never have to rev it (and, of course, with no references to external constants) you can probably get away with not updating it which will keep your customer's extensions from getting crusty.
I guess this is kind of a follow-on to question 1522329.
That question talked about getting a list of all classes used at runtime via the java -verbose:class option.
What I'm interested in is automating the build of a JAR file which contains my class(es), and all other classes they rely on. Typically, this would be where I am using code from some third party open source product's "client logic" but they haven't provided a clean set of client API objects. Their complete set of code goes server-side, but I only need the necessary client bits.
This would seem a common issue but I haven't seen anything (e.g. in Eclipse) which helps with this. Am I missing something?
Of course I can still do it manually by: biting the bullet and including all the third-party code in a massive JAR (offending my purist sensibilities) / source walkthrough / trial and error / -verbose:class type stuff (but the latter wouldn't work where, say, my code runs as part of a J2EE servlet, and thus I only want to see this for a given Tomcat webapp and, ideally, only for classes related to my classes therein).
I would recommend using a build system such as Ant or Maven. Maven is designed with Java in mind, and is what I use pretty much exclusively. You can even have Maven assemble (using the assembly plugin) all of the dependent classes into one large jar file, so you don't have to worry about dependencies.
http://maven.apache.org/
Edit:
Regarding the servlet, you can also define which dependencies you want packaged up with your jar, and if you are making a stand alone application you can have the jar tool make an executable jar.
note: yes, I am a bit of a Maven advocate, as it has made the project I work on much easier. No I do not work on the project personally. :)
Take a look at ProGuard.
ProGuard is a free Java class file shrinker, optimizer, obfuscator, and preverifier. It detects and removes unused classes, fields, methods, and attributes. It optimizes bytecode and removes unused instructions. It renames the remaining classes, fields, and methods using short meaningless names. Finally, it preverifies the processed code for Java 6 or for Java Micro Edition.
What you want is not only to include the classes you rely on but also the classes, the classes you rely on, rely on. And so on, and so forth.
So that's not really a build problem, but more a dependency one. To answer your question, you can either solve this with Maven (apparently) or Ant + Ivy.
I work with Ivy and I sometimes build "ueber-jar" using the zipgroupfileset functionality of the Ant Jar task. Not very elegant would say some, but it's done in 10 seconds :-)
This has been bugging me for years now, and I thought one of you fine people would know - in Eclipse's .classpath files, what is the combineaccessrules attribute of the classpathentry element actually used for?
I can see in the Java Build Path config dialog that it can be maniuplated, but I can't think of a good use case for it. If I muck about with the settings, or modify the .classpath file manually, it doesn't seem to have any effect.
I'm hoping someone else has put it to good use, and I can steal their ideas. Basically, it's an itch I'm trying to scratch.
With proper use of access rules you can prevent using "internal" and/or "non-api" classes and methods. When you add a class or package as Forbidden or Discouraged the compiler show an error or warning when you use that class or class from the specified package. For a longer introduction of access rules you should read this short article.
For using combine access rules imagine the following situation:
You have 2 projects, A and B.
On the classpath of project A there is a jar file that is exported. The jar contains some "stable api", "unstable api" and "non-api" public classes.
Project B depends on project A.
You do not allow using "non-api" classes in project A so you set some Forbidden access rules on those classes / packages.
In project B you do not allow using "non-api" as well, but you do want to get a warning when using "unstable api". In this case in project B you only have to set the additional Discouraged access rules if you check the Combine rules with the access rules of the exported project entries.
Access rules are handy little things, but dangerous. They exclude a source file from the project compiler but leave the file intact in the filesystem.
The project I work on has a bootstrap class in one of our source folders, but if we include the entire folder the project classpath it won't compile (it's a long story and the build process handles this).
So we use an eclipse access rule to exclude it and it never bothers us during development. This means we can't easily change the code, but it's one of those classes that literally hasn't been touched in years.
Combine Access Rules, judging by the JavaDoc, is a real edge use case. To use it you would have to have:
an access rule in an exported source entry of one project
a link to that project from a parent project
a need to combine the access rules of the sub project with the parent
I really can't say how it would be useful, but I hope that at least answers your "what is it" question :)
although i have never used it myself, a little bit of into can be found here.
whether the access rules of the project's exported entries should be combined with this entry's access rules
the access rules would be something like including "com/tests/**"
OSGi has a problem with split packages, i.e. same package but hosted in multiple bundles.
Are there any edge cases that split packages might pose problems in plain java (without OSGi) ?
Just curious.
Where split packages come from
Split packages (in OSGi) occur when the manifest header Require-Bundle is used (as it is, I believe, in Eclipse's manifests). Require-Bundle names other bundles which are used to search for classes (if the package isn't Imported). The search happens before the bundles own classpath is searched. This allows the classes for a single package to be loaded from the exports of multiple bundles (probably distinct jars).
The OSGi spec (4.1) section 3.13 describes Require-Bundle and has a long list of (unexpected) consequences of using this header (ought this header be deprecated?), one section of which is devoted to split packages. Some of these consequences are bizarre (and rather OSGi-specific) but most are avoided if you understand one thing:
if a class (in a package) is provided by more than one bundle then you are in trouble.
If the package pieces are disjoint, then all should be well, except that you might not have the classes visible everywhere and package visibility members might appear to be private if viewed from a "wrong" part of a split package.
[Of course that's too simple—multiple versions of packages can be installed—but from the application's point of view at any one time all classes from a package should be sourced from a single module.]
What happens in 'standard Java'
In standard Java, without fancy class-loaders, you have a classpath, and the order of searching of jars (and directories) for classes to load is fixed and well-defined: what you get is what you get. (But then, we give up manageable modularity.)
Sure, you can have split packages—it's quite common in fact—and it is an indication of poor modularity. The symptoms can be obscure compile/build-time errors, but in the case of multiple class implementations (one over-rides the rest in a single class-path) it most often produces obscure run-time behaviour, owing to subtly-different semantics.
If you are lucky you end up looking at the wrong code—without realising it—and asking yourself "but how can that possibly be doing that?"If you are unlucky you are looking at the right code and asking exactly the same thing—because something else was producing unexpected answers.
This is not entirely unlike the old database adage: "if you record the same piece of information in two places, pretty soon it won't be the same anymore". Our problem is that 'pretty soon' isn't normally soon enough.
For OSGi packages in different bundles are different, regardless of their name, because each bundle uses its own class loader. It is not a problem but a feature, to ensure encapsulation of bundles.
So in plain Java this is normally not a problem, until you start using some framework that uses class loaders. That is typically the case when components are loaded.
Splitting packages across jars probably isn't a great idea. I suggest making all packages within jars sealed (put "Sealed: true" in the main section of the manifest). Sealed packages can't be split between jars.
In the case of OSGi, classes with the same package name but a different class loader are treated as if they are in different packages.
You'll get a nasty runtime error if you have classes in the same package and some are in a signed JAR while others are not.
Are you asking because the package in question is yours, not third party code?
An easy example would be a web app with service and persistence layers as separate OSGi bundles. The persistence interfaces would have to be shared by both bundles.
If I've interpreted your question correctly, would the solution be to create a sealed JAR containing the shared interfaces and make it part of both bundles?
I don't mean to try and hijack the thread. I'm asking for clarification and some better insight from those who might have done more with OSGi to date than I have.