Lite version of a Java software - java

Our software currently has many features. I've been asked to make a free trial version which consist of a lightweight version of the full software. Only a few specific features would be available in the trial. And since a jar file isn't encrypted, I was relunctant to release a full version with hardcoded restrictions. I want to be able to have 2 jars : 1 containing the basic features and 1 with the advanced features.
The features are in different menus. It would be nice it the code would try to load the jar with the extra features at start up and display a message (like : this feature is unvailable in the trial) when the non-paying user selects an advanced menu. On the other hand, a paying user with access to the advanced features jar wouldn't know the difference (I'm talking about the difference between now, 1 jar, and the new method, 2 separate jars).
Any tip on how to proceed ?
Any warning on common mistakes to avoid ?
Any better strategy than the separate jars ?
Edit : The best suggestion so far describes how to do my crippleware, but also warns me not to do a crippleware. So what do should I do ?

As you mentioned, you would probably have 2 jars:
1 with the basic features and stubs for the advanced features.
1 with the actual advanced features.
You could use a factory class with a config setting to determine whether to create the stub classes or the real classes - e.g. "FancyFeatureClass" or "FancyFeatureClassStub". "FancyFeatureClassStub" would be included in the "lite" distribution, but "FancyFeatureClass" would only be in the advanced features jar.
If they tried to change the config setting to create the real class without having the jar with the real classes, they would just end up getting class not found errors.
When upgrading, add advanced features jar to the classpath and change the config setting to tell the factory class to create the real classes instead of the stubs. Assuming your app could be split up that way, it should work fine.
As for common mistakes - I think you've already made one - probably not your fault though :)
"Crippleware" is a bad way to evaluate a product. Better to release a full featured version with an expiration or a nag screen than to release a crippled product. Not having those advanced features would probably make it difficult for someone to really evaluate the product.

Many technologies allow pluggable features (called plugins or addons usually).
The idea is that your core code (or framework) declares some interfaces (a well-thought API is ideal). Plugins can provide new implementations of an interface, and register it to the framework.
In its boot sequence, your framework will look (through some convention, in a file for example) if there are plugins, and give them a chance to execute their own boot sequence, consisting of the registration.
After the boot phase, a runtime example (for menus) : The framework looks it the registry where he stores the menus. The registry contains the menus the framework himself declared, plus any additionals provided by plugins... It displays all of them.
If you want specifically the behavior you asked for, I would implement this as follow :
menus available in all cases are declared and implemented in the framework
menus available only in the expanded edition are implemented twice :
in the framework, the implementation would simply display a message
(like : this feature is unvailable in the trial
in the plugin (= paid edition), it would override the previous implementation with the real one, that does the real job.
That way, you paying users have all normal functionality, with the trial version shows the warnings.
Many technologies exist to implement this, the best choice depends on what you already know/use/feel confortable with :
interface implementation is plain java, a string in the manifest of your plugin jar can mention the class to start.
Eclipse RCP has full implementation of menus that way (so you would have nothing to code, only configuration)
Spring is also pretty good when you use interfaces ...

Using a separate Jar which implements the paid for features (and a separate lite front end that displays a suitable message like 'not available' if it gets a ClassNotFoundException) would be the simplest way to do it.
There are many frameworks, up to and including Eclipse RCP for distributing UI applications in a modular form - but this will be overkill for your needs.
In fact, you don't even need two Jars, as long as your build process has the option to compile/package a sub-set of the Java classes in the Jar that you build as part of the distribution process. Just don't include the paid for features.

Related

Is there a maven plugin that augments Java access control?

Is there a maven plugin that makes mvn verify of an aggregating project fail when its submodules or their transitive dependencies depend on things they oughtn't.
I'd like to be able to restrict uses of public APIs to express policies like
Only classes or packages on a whitelist can invoke this public constructor/method.
This public setter that was produced by a code generator should not be called -- it should really have been package-private.
Motivation & Caveats
I realize that there are ways to work around these requirements using reflection and deserialization. My end goal is to allow system-architects & tech-leads to set a policy like
All uses of security-critical APIs should be in modules reviewed by security. Contact them if you need the whitelist expanded.
These deprecated APIs are banned in favor of new ones. There's a whitelist for grandfathered code which should shrink over time.
The system architect treats trusts application developers but we want naive policy violations flagged with useful error messages, and we want developers who hack around the policy to not be able to plausibly deny that they did so.
Tricks like reflection and deserialization fall into that not-plausibly-deniable hacking.
This is kind of like some of the aims of Jigsaw, where a module (group of packages) can declare that its public interface is limited to just some packages, but jigsaw isn't widely available.
This question differs from "Make Java methods visible to only specific classes" because I'm not asking about ways to do this from within the Java language.
You can use checkstyle to perform such checks, for your use case you could use import control:
It seems that this doesn't support fully-qualified imports, based on following answers:
Checkstyle rule to limit interactions between root packages (with ImportControl?)
How to prevent fully qualified names in Java code
As the second answer suggest you could work around that by forbidding fully qualified imports by using another tool - PMD.
As for JSPs, these are usually compiled in the servlet container, nevertheless there is a way to pre-compile these as well, using maven plugin.

the definitive way to generate a classpath for javax.tools.JavaCompiler in OSGi

[Clarification] Forgive the lack of clarity in the initial description. Allow me to re-phrase the question.
Does there exist a way to perform runtime compilation using the javax.tools API, usable in OSGi (again stressing runtime), which understands a bundle's dependencies and security constraints?
[update]
Please see https://github.com/rotty3000/phidias
It's a well formed OSGi bundle.
The readme provides all the details of the very tiny 4 class API (8k module).
In order to get from a set of package imports and exports to a list of bundles which can be used for compilation, you'll need some sort of repository of candidate bundles, and a provisioner to work out which bundles best provide which packages. If you're using 'Require-Bundle' (not a best practice), you'll know the bundle names, but not necessarily the versions, so some provisioning is still required.
For example, in Eclipse PDE, the target platform is used as the basic repository for compilation. You can also do more sophisticated things like using Eclipse's p2 provisioning to provision your target platform, so you can use an external p2 repository as your repository instead of setting one up yourself. For command line builds, Tycho allows Maven builds to use the same sort of mechanisms for resolving the classpath as Eclipse itself uses.
An alternative approach is to list your 'classpath' as Maven dependencies, and let the maven bundle plugin (based on bnd) generate your manifest for you.
If you can't take advantage of existing command line tools because you're compiling programatically (it's not entirely clear from your question what problem you're trying to solve), your best best is probably to take advantage of an existing provisioning technology, like OBR, Eclipse p2, or Apache Ace to work out the bundles which should be on the class path for compilation.
This is exactly what we do in bndtools ... If I had a bit of time I would add a compiler to bnd so it could also do this.
Sure you can, you just have to write a custom JavaFileManager which will supply the right classes to compile against to the JavaCompiler.
For example you can write one that gets its classes from an OSGi runtime. If you don't mind having a dependency from your compiler bundle to the libraries you need then it's pretty easy, otherwise you can use the wiring api to look to other bundles as well. (OSGi 4.3+ only). If you intercept which packages it requests while compiling you can generate Package-Import statements so you can generate a bundle.
I made a rough GitHub example a few months back:
https://github.com/flyaruu/test-dynamic-compiler
There were some issues (I couldn't get the Eclipse ecj compiler to work for example, I didn't look into bundle security at all, and due to the dynamic nature of OSGi you have to listen to bundle changes to update your compilation path.), but it works fine.
I've so far found that the real answer is "No there is not!"
The predominant runtime compilation scenario currently for java is JSP compilation. An investigation of the app servers I've had the occasion to review use one of these methods:
invocation of javac (through a system call)
use of ecj/jdt
uses javax.tools in a non-OSGi aware way
All of these approaches are based on collecting the available classpath by directly introspecting jars or classes in the file system.
None of the current approaches are aware of OSGi characteristics like the dynamic nature of the environment or the underlying restrictions imposed of the framework itself.

Introduce per-customer personalization in java application

I've searched on internet and here on SO, but couldn't wrap my mind around the various options.
What I need is a way to be able to introduce customer specific customization in any point of my app, in an "external" way, external as in "add drop-in jar and get the customized behavior".
I know that I should implement some sort of plugin system, but I really don't know where to start.
I've read some comment about spring, osgi, etc, can't figure out what is the best approach.
Currently, I have a really simple structure like this:
com.mycompany.module.client.jar // client side applet
com.mycompany.module.server.jar // server side services
I need a way of doing something like:
1) extend com.mycompany.module.client.MyClass as com.mycompany.module.client.MyCustomerClass
2) jar it separately from the "standard" jars: com.mycompany.customer.client.jar
3) drop in the jar
4) start the application, and have MyCustomerClass used everywhere the original MyClass was used.
Also, since the existing application is pretty big and based on a custom third-party framework, I can't introduce devastating changes.
Which is the best way of doing this?
Also, I need the solution to be doable with java 1.5, since the above mentioned third-party framework requires it.
Spring 3.1 is probably the easiest way to go about implementing this, as their dependency injection framework provides exactly what you need. With Spring 3.1's introduction of Bean Profiles, separating concerns can be even easier.
But integrating Spring into an existing project can be challenging, as there is some core architecture that must be created. If you are looking for a quick and non-invasive solution, using Spring containers programmatically may be an ideal approach.
Once you've initialized your Spring container in your startup code, you can explicitly access beans of a given interface by simply querying the container. Placing a single jar file with the necessary configuration classes on the classpath will essentially automatically include them.
Personalization depends on the application design strongly. You can search for a pluggable application on the Internet and read a good article (for an example: http://solitarygeek.com/java/a-simple-pluggable-java-application). In the pluggable application, you can add or remove a feature that a user decides. A way for the pluggable application is using the Interface for de-coupling of API layer and its implementation.
There is a good article in here
User personalisation is something which needs to be in the design. What you can change as an after thought if the main body of code cannot be changed, is likely to be very limited.
You need to start be identifying what can be changed on a per user basis. As it appears this cannot be changed, this is your main limiting factor. From this list determine what would be useful to change and implement this.

Conditional Java Package Distributions

I know there isn't such a thing as conditional compilation as in C/C++ but I wonder if it is possible to produce a java program conditionally based on requirements. For example, there could be a public version which contains some features and private version which contains more features.
Am I right to believe that the only way to achieve this is with the help of something like plugins, i.e. the different features are found dynamically if they are present in the classpath?
I would have multiple modules for your application and multiple jars. I would have all the "private" features in a jar by itself and the rest in one or more jars.
Your application would then use the features which are available in the jars distributed (there are any number of ways to do this)
A library which you might find useful is Reflections This library allows you to find all the class which implement interface or have an annotation. So you could have a Feature interface and ask it to give you all the class which are Features
It is not unusual to separate a java package into using interfaces and implementations of those interfaces.
At package time you can filter out/in the implementations based upon conditions by using Ant or Maven. Like a different and more feature rich implementation for private versions.
Checking the classpath is ok, but a better bet is to use JNDI and let separate parts of your application find each other by registering them self into a shared JDNI context.
You can easily achieve that in a OOPS way.
Organize the features as following
Interface Feature
Class BaseFeature
Class BasicFeature1
Class BasicFeature2
Class SpecialFeature1
Class SpecialFeature2
Class PremiumFeature1
...
Then load the features centrally by having some sort of FeaturesManager
class FeatureManager {
String[] globalFeatureClasses = new String[]{--list all of them here, or load an external list etc--};
for each feature in globalFeaturesList {
if (class.forName(feature) != null) { // class is available
// this feature available
} else {
// this feature is not available
}
}
}
The features will implement other interfaces to provide behaviour etc.
You can then build distribution packages containing just the basic features, basic + advanced features or premium version containing all features including premium ones. Because the application will automatically detect available features, you can ship them later as well in jars which just need to be placed on classpath along others.
Ofcourse this design needs to be developed further to be effectively used, but you get the idea.

Java IoC : distributed configuration

I'm building a J2EE application in which I want to allows plugins. I'm fairly convince of the goodness of IoC framework, and so the application will have one to manage services.
Now, I want to allows plugins to be added as simple JAR dropped in the classpath + perhaps a simple configuration file to edit to activate them, in no way something looking like Spring XML config files.
Most of the plugin architecture will be base around strategy/pipeline/chain of command patterns: for example the best plugin for an action is chosen by strategy, several plugins add filtering actions to an user input thanks to a pipeline, and so one.
So, I want to be able to:
define service interfaces in the core application,
set-up core implementation for extensible services with the chosen pattern in the main application,
let third party plugins register themselves in these hooks.
The first 2 points are quite easy, with or without IoC. The last one seems more complex without support at the IoC container level, or at least there is a lot of plumbing to do (how to manage classpath/sevice discovery, how to manage service orders in pipeline when the context change (new plugins), how to manage service overriding, etc).
I do know that Tapestry5 is great in that regards[1], but I can't find anything really relevant for Spring and Guice. And my company is more a String/Guice one than a T5 one (well, if I'm able to show that it's the best solution...)
So I'm wondering:
if I missed some obvious documentation;
if my requirement are so specials;
if an IoC container is not the right tool for that, and I should look for OSGi or something else.
Thanks for any tips !
[1] http://tapestry.apache.org/tapestry5.1/tapestry-ioc/configuration.html
I'm not sure how this would work with exactly what you're looking to do, but Guice's basic mechanic for handling plugins is Multibindings. How you handle discovery of plugins is up to you, but there are a variety of choices including scanning the classpath for implementations of plugin interfaces, having plugins provide a Module that adds their implementation(s) to the multibinder(s), using a config file that lists the plugin implementation classes, etc.
As the link mentions, you'd need OSGi if you need plugins to be addable at runtime with no restart.
Have you considered having a look at the Java EE 6 solution - CDI, implementation is named Weld based on JBoss Seam - which might be useful?
Once you start dropping in jars and their dependencies and then go though a couple of iterations of this with different plugins and different dependency versions, then you will start to feel the pain that many "application host containers" succumb to.
One possible solution to this problem is OSGi, although I did note a Tapestry blog highlighting the pitfalls of the OSGi approach:
http://blog.tapestry5.de/index.php/2010/01/19/tapestry-ioc-modularization-of-web-applications-without-osgi/

Categories

Resources