I have 2 Java packages, A & B. Let's say that some classes in package B want to use some classes in package A however, when a developer comes along and develops package C (or, say, application C), he/she will use my package B but I do not want him/her to be able to use the classes in A that B is using. That is to say, I want my classes in package A to be package private so that they are hidden from the application developer. However, I do want my own package B to be able to access those classes which are package private. Can this be done in Java? Do I basically just need to bite the bullet and make the classes public and just hope that the user doesn't try to use them? Or, do I need to replicate the classes that are in A inside of B?
My preference would be something that is not hack-y (i.e. I don't want to use reflection). Help?
You can do it with JDK 8 and its Project Jigsaw. You might want to give a look to Project Jigsaw Quickstart Guide.
Unfortunately, Jigsaw is part of the JDK8, and it is not totally ready yet. It is not expected to be feature complete until January 2013 and will not be released before midyear 2013.
However, you can already compile your classes with the JDK 8 preview and make your ideas work.
In this case, your problem can be solved by dividing your application in independent modules. You could do something like:
module foo {
exports foo;
permits bar;
permits baz;
}
Here the module foo can be required only by modules named bar or baz. A dependence from a module of some other name upon foo will not be resolvable at compile time, install time, or run time. If no permits clauses are present then there are no such constraints.
Not sure if alternative frameworks like OSGI, of which you can find implementations in Apache Felix and Eclipse Equinox offer some kind of functionality to implement these levels of encapsulation. It is probable that you may want to investigate a bit about that.
The problem with OSGi without the existence of Jigsaw is that whatever rules enforced by the framework can be broken by reflection, once Jigsaw is ready for public use, though, these rules will be enforced by Java itself, as you read above, at compile time, runtime and install time.
You can do this with OSGi. Android and JDK 6 as target are not a problem in this case, there are OSGi frameworks running on Android -> e.g. see mBedded Server for Android. You can download a free non-commercial version from the link.
You have several options how to do it in OSGi, depending on what you want to achieve.
Option 1 (recommended):
You can put packages A and B in one and the same bundle AB, and export only package B in the manifest of this bundle with Export-Package.
Package/application C or any other "user" app can import package B and use it. And it cannot use and doesn't even see package A, because it is internal for the bundle AB. You don't need any special declarations or dependencies on Java level; this will work with ANY Jva version, because the modularity and the separate bundle spaces are part of the OSGi basics and don't depend on the latest Java version or smth.
Option 2:
If for some reason you want packages A and B separated in different bundles, you can have them so, you'll export and import the packages in the manifest and then control which bundle has the right to import which package by using Permissions (see OSGi Permission and Conditional Permission services). However, this is more complicated to realize.
Option 3: You can also put package A in a Fragment bundle and allow it to attach to the bundle containing B. In this way B will have access to package A, but at the same time you'll be able to update package A separately during runtime if you want. Since packages in fragments are treated as private for the host bundle (in this case host is the bundle containing package B), Bundle C won't see A. It will only see what is exported by Bundle B.
Since you are not that familiar with OSGi, I will recommend to start witl Option 1 and then later if needed you can upgrade your approach to Option 3 if you want.
#Edwin Dalorzo : It is definitely not true that the rules in OSGi can be broken by reflection. Bundles have separate classloaders in OSGi. You can reflect from Bundle C as much as you won't for the classes A and the only thing you'll get is a ClassNotFound exception - believe me, I have seen it enough times ;)
Related
Just as shown in the picture, one app (Java) referenced two third-party package jars (packageA and packageB), and they referenced packageC-0.1 and packageC-0.2 respectively. It would work well if packageC-0.2 was compatible with packageC-0.1. However sometimes packageA used something that could not be supported in packageC-0.2 and Maven can only use the latest version of a jar. This issue is also known as "Jar Hell".
It would be difficult in practice to rewrite package A or force its developers to update packageC to 0.2.
How do you tackle with these problems? This often happens in large-scale companies.
I have to declare that this problem is mostly occurred in BIG companies due to the fact that big company has a lot of departments and it would be very expensive to let the whole company update one dependency each time certain developers use new features of new version of some dependency jars. And this is not big deal in small companies.
Any response will be highly appreciated.
Let me throw away a brick in order to get a gem first.
Alibaba is one of the largest E-Commerces in the world. And we tackle with these problems by creating an isolation container named Pandora. Its principle is simple: packaging those middle-wares together and load them with different ClassLoaders so that they can work well together even they referenced same packages with different versions. But this need a runtime environment provided by Pandora which is running as a tomcat process. I have to admit that this is a heavy plan. Pandora is developed based on a fact that JVM identifies one class by class-loader plus classname.
If you know someone maybe know the answers, share the link with him/her.
We are a large company and we have this problem a lot. We have large dependency trees that over several developer groups. What we do:
We manage versions by BOMs (lists of Maven dependencyManagement) of "recommended versions" that are published by the maintainers of the jars. This way, we make sure that recent versions of the artifacts are used.
We try to reduce the large dependency trees by separating the functionality that is used inside a developer group from the one that they offer to other groups.
But I admit that we are still trying to find better strategies. Let me also mention that using "microservices" is a strategy against this problem, but in many cases it is not a valid strategy for us (mainly because we could not have global transactions on databases any more).
This is a common problem in the java world.
Your best options are to regularly maintain and update dependencies of both packageA and packageB.
If you have control over those applications - make time to do it. If you don't have control, demand that the vendor or author make regular updates.
If both packageA and packageB are used internally, you can use the following practise: have all internal projects in your company refer to a parent in the maven pom.xml that defines "up to date" versions of commonly used third party libraries.
For example:
<framework.jersey>2.27</framework.jersey>
<framework.spring>4.3.18.RELEASE</framework.spring>
<framework.spring.security>4.2.7.RELEASE</framework.spring.security>
Therefore, if your project "A" uses spring, if they use the latest version of your company's "parent" pom, they should both use 4.3.18.RELEASE.
When a new version of spring is released and desirable, you update your company's parent pom, and force all other projects to use that latest version.
This will solve many of these dependency mismatch issues.
Don't worry, it's common in the java world, you're not alone. Just google "jar hell" and you can understand the issue in the broader context.
By the way mvn dependency:tree is your friend for isolating these dependency problems.
I agree with the answer of #JF Meier ,In Maven multi-module project, the dependency management node is usually defined in the parent POM file when doing unified version management. The content of dependencies node declared by the node class is about the resource version of unified definition. The resources in the directly defined dependencies node need not be introduced into the version phase. The contents of the customs are as follows:
in the parent pom
<dependencyManagement>
<dependencies >
<dependency >
<groupId>com.devzuz.mvnbook.proficio</groupId>
<artifactId>proficio-model</artifactId>
<version>${project.version}</version>
</dependency >
</dependencies >
</dependencyManagement>
in your module ,you do not need to set the version
<dependencies >
<dependency >
<groupId>com.devzuz.mvnbook.proficio</groupId>
<artifactId>proficio-model</artifactId>
</dependency >
</dependencies >
This will avoid the problem of inconsistency .
This question can't be answered in general.
In the past we usually just didn't use dependencies of different versions. If the version was changed, team-/company-wide refactoring was necessary. I doubt it is possible with most build tools.
But to answer your question..
Simple answer: Don't use two versions of one dependency within one compilation unit (usually a module)
But if you really have to do this, you could write a wrapper module that references to the legacy version of the library.
But my personal opinion is that within one module there should not be the need for these constructs because "one module" should be relatively small to be manageable. Otherwise it might be a strong indicator that the project could use some modularization refactoring. However, I know very well that some projects of "large-scale companies" can be a huge mess where no 'good' option is available. I guess you are talking about a situation where packageA is owned by a different team than packageB... and this is generally a very bad design decision due to the lack of separation and inherent dependency problems.
First of all, try to avoid the problem. As mentioned in #Henry's comment, don't use 3rd party libraries for trivial tasks.
However, we all use libraries. And sometimes we end up with the problem you describe, where we need two different versions of the same library. If library 'C' has removed and added some APIs between the two versions, and the removed APIs are needed by 'A', while 'B' needs the new ones, you have an issue.
In my company, we run our Java code inside an OSGi container. Using OSGi, you can modularize your code in "bundles", which are jar files with some special directives in their manifest file. Each bundle jar has its own classloader, so two bundles can use different versions of the same library. In your example, you could split your application code that uses 'packageA' into one bundle, and the code that uses 'packageB' in another. The two bundles can call each others APIs, and it will all work fine as long as your bundles do not use 'packageC' classes in the signature of the methods used by the other bundle (known as API leakage).
To get started with OSGi, you can e.g. take a look at OSGi enRoute.
Let me throw away a brick in order to get a gem first.
Alibaba is one of the largest E-Commerces in the world. And we tackle with these problems by creating an isolation container named Pandora. Its principle is simple: packaging those middle-wares together and load them with different ClassLoaders so that they can work well together even they referenced same packages with different versions. But this need a runtime environment provided by Pandora which is running as a tomcat process. I have to admit that this is a heavy plan.
Pandora is developed based on a fact that JVM identifies one class by class-loader plus classname.
I am supposed to deliver a SDK in Java for the company I work for.
I have a few years of Java EE experience but not so much when it comes to develop API and SDK.
The problem here, is that the SDK is already available in .NET C# and working just fine. I made it myself.
Switching to Java is a nightmare. I tried several solutions. All failed, some were inconclusive due to the fact I could not progress.
As the title says, I a need to develop a Java Library that has modules. Internal modules. Modules the world out there is NOT supposed to see / use / modify.
In C#, it's easy as pie : create your modules respective namespace, make their classes and methods privates, expose one or more wrappers (bridges) to the entire assembly (project) with internal so that the "main module", through it's own public wrapper accessible by the world, can use the tools provided within these internals modules.
The keyword, here, is INTERNAL. I think it's pretty easy to understand. So let's take an example.
Let's say the SDK is consisting of 4 modules.
The 1st module, is the main module, the one that is public and
exposed to the whole world. In other words, the unique entry point
of the SDK. It's like a master of its own universe. It can use the
internal modules at will, but will never show them to the world.
Never.
The 2nd module is network-related. As in, it deals with network to manage connexions to remote services, read and write data from and to a stream. It offers its own little wrapper so that the main module does not need to use the 2nd module internal tools. Like a universe inside a universe.
The 3rd module is a data processing module. It receives packets (hand-made by the 2nd module) so that it can be processed and relevant information dealt with.
So here we are. How can I do that in Java using NetBeans ?
I tried Maven with POM Project, and Netbeans modules. A nightmare.
I tried creating multiple libraries (one per module), tweaked the Main Module library to include its (modules) dependancies but it does not work.
In a standard Java EE console application, as soon as I attempt to instanciate my SDK Manager (ergo the main wrapper from the main module), it fails because Class Not Found exception : could not find classes related to the internal sub-modules.
If I add all modules respective Jar into this Java Console app, it can access all wrappers. Where is the fun in that ?
Thanks for the help !
Project Jigsaw will eventually give you what you want when java 9 comes out.
See this article about how jigsaw works, in particular,
An exports clause in a module declaration makes the public types in
the package it names available to other modules, so we can with Jigsaw
defines boundaries, and not all public types could be used from other
modules, we must explicitly specify which types are visible.
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.
getting started with osgi, i wonder what's the conceptual diffence between bundles and components. And when to use which of them. Any pointers are welcome.
EDIT:
Components and Bundles provide different interfaces and therefore they are probably not interchangeable
ComponentContext
BundleContext
A component is:
an active participant in the system
aware of and adapt to its environment
environment = services provided by other components
environment = resources, devices, ...
may provide services to other components and use services from other components
have a lifecycle
In short:
Component provide services
Bundle manage the lifecycle
A bundle can have only one activator (needing a BundleContext), and can have as many active components as you want.
That means you may end up trying to fit in one activator several loosely-related concerns into a single class.
That is why it may be easier to manage those components by Declarative Services, through the SCR (the "Service Component Runtime" which is an "extender bundle" implementing the new and improved OSGi R4.2 DS - Declarative Service - specification).
This is especially true since OSGi 4.2 because it is now much easier to write DS components as POJOs: the activate and deactivate methods are no longer required to take a ComponentContext parameter. See also Lazy Declarative Service.
Note:
It can help to replace those terms in the context of OSGi and look at "how we got there" (excellent blog post by Neil Bartlett)
Here are some relevant extracts, where the "modules" end up being the OSGi Bundles (managing Components which declare Services):
Module Separation
Our first requirement is to cleanly separate modules so that classes from one module do not have the uncontrolled ability to see and obscure classes from other modules.
In traditional Java the so-called “classpath” is an enormous list of classes, and if multiple classes happen to have the same fully-qualified name then the first will always be found and the second and all others will be ignored.
The way to prevent uncontrolled visibility and obscuring of classes is to create a class loader for each module. A class loader is able to load only the classes it knows about directly, which in our system would be the contents of a single module.
Module Access level
If we stop here then modules will be completely isolated and unable to communicate with each other. To make the system practical we need to add back in the ability to see classes in other modules, but we do it in a careful and constrained way.
At this point we input another requirement: modules would like the ability to hide some of their implementation details.
We would like to have a “module” access level, but the problem today is that the javac compiler has no idea where the module boundaries lie.
The solution we choose in our module system is to allow modules to “export” only portions of their contents. If some part of a module is non-exported then it simply cannot be seen by other modules.
When importing, we should import what we actually need to use, irrespective of where it comes from and ignoring all the things that happen to be packaged alongside it.
Granularity of Exports and Imports
OSGi chooses packages.
The contents of a Java package are intended to be somewhat coherent, but it is not too onerous to list packages as imports and exports, and it doesn’t break anything to put some packages in one module and other packages in another module.
Code that is supposed to be internal to our module can be placed in one or more non-exported packages.
Package Wiring
Now that we have a model for how modules isolate themselves and then reconnect, we can imagine building a framework that constructs concrete runtime instances of these modules. It would be responsible for installing modules and constructing class loaders that know about the contents of their respective modules.
Then it would look at the imports of newly installed modules and trying to find matching exports.
An unexpected benefit from this is we can dynamically install, update and uninstall modules. Installing a new module has no effect on those modules that are already resolved, though it may enable some previously unresolvable modules to be resolved. When uninstalling or updating, the framework knows exactly which modules are affected and it will change their state if necessary.
Versions
Our module system is looking good, but we cannot yet handle the changes that inevitably occur in modules over time. We need to support versions.
How do we do this? First, an exporter can simply state some useful information about the packages it is exporting: “this is version 1.0.0 of the API”. An importer can now import only the version that is compatible with what it expects and has been compiled/tested against, and refuse to accept
Packaging Modules and Metadata
Our module system will need a way to package the contents of a module along with metadata describing the imports and exports into a deployable unit.
So the only question is, where should we put the metadata, i.e. the lists of imports and exports, versions and so on?
As it happens OSGi was designed before 2000, so it did choose either of these solutions. Instead it looked back at the JAR File Specification, where the answer is spelled out:
META-INF/MANIFEST.MF is the standard location for arbitrary application-specific metadata.
Late Binding
The final piece of modularity puzzle is late binding of implementations to interfaces. I would argue that it is a crucial feature of modularity, even though some module systems ignore it entirely, or at least consider it out of scope.
We should look for a decentralised approach.
Rather than being told what to do by the God Class, let us suppose that each module can simply create objects and publish them somewhere that the other modules can find them. We call these published objects “services”, and the place where they are published the “service registry”.
The most important information about a service is the interface (or interfaces) that it implements, so we can use that as the primary registration key.
Now a module needing to find instances of a particular interface can simply query the registry and find out what services are available at that time. The registry itself is still a central component existing outside of any module, but it is not “God”… rather, it is like a shared whiteboard.
In OSGi terminology a "component" is like a run-time service. Each component has an implementation class, and can optionally implement a public interface, effectively providing this "service". This aspect of OSGi is sometimes likened to a service registry pattern.
Components in OSGi are, by definition, provided by a bundle. A bundle may contain/provide multiple components. While by itself a bundle may not provide a service, components/declarative services are used to make OSGi more service oriented. You are under no obligation to use components/services.
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.