Define Jodd Madvoc mappings from external file - java

I am using Jodd Madvoc web framework and define actions (classes and methods) using annotations. Everything works fine, but now I need to have these action definitions in an external file, so Madvoc don't need to scan my class path for the action classes (and for some other reasons).
I could probably code this by myself, since Madvoc is quite open for extension, but just wonder if there is already a way to do this?
Thank you!

What you are asking for is the so-called routing file. And the answer is: yes, Madvoc has support for routing files, since v3.6 (that was one of the new features, so thats maybe why you didn't know about it:). Anyway, all you have to do is to have a route file and use different configurator: RouteMadvocConfigurator instead of default one. This configurator reads routing file from the class path and defines the actions from it. You should be able to specify all action flags using routing file, including async flag, interceptors and so on. Nice thing about the routing file is that it's syntax is not so strict, so you can make your own format easily.
Here is an example of routing file:
`/hello.html` "jodd.madvoc.action.HelloAction#view"
GET /helloWorld.html jodd.madvoc.action.HelloAction#world
/zigzag/${id} jodd.madvoc.action.ArgsAction#zigzag /zigzag
As said, the format is loose, so you can e.g. define http method name everywhere you like in the line and so on.
You can see more details in official documentation.

Related

Eclipse-RCP: Getting Resourcebundles using custom ResourceBundle.Control

We load our translations from our database. To retrieve the bundles we have a custom java.util.ResourceBundle.Control.
To translate our e4 RCP application, I already created a TranslationService, which I add to the root context using an addon. That was no problem (only that I had to copy 95% of BundleTranslationProvider because I did not see any other way).
Now I want to use the new Message Extension (coming with Eclipse Luna) to translate the rest. As far as I can see from the sources of the default MessageFactoryServiceImpl, there does not seem to be an easy way to inject my ResourceBundle.Control there either.
In the linked blog series, the use case of getting the resource bundles from a database is described, but solved by using class based resource bundles. This is no option, because I can't implement a class for every resource bundle and every locale. The reason for loading the resource bundles from the database is to be able to deploy translations into new languages without redeploying the application.
Is the only way to achive this by creating my own IMessageFactoryService by copying 99% of the default MessageFactoryServiceImpl, just to pass our Control into the calls to ResourceBundleHelper?
After some investigation on this, I found a way that you are able to support your use case without modifying or copying code a lot.
You need to exchange the BundleLocalization to load the ResourceBundle your way. In your case by using your custom ResourceBundle.Control. By doing this you override that the platform is looking for the ResourceBundle specified by the MANIFEST.
At the moment you will also have to implement a custom TranslationService that uses your BundleLocalization. The existing BundleTranslationProvider does not take the BundleLocalization out of the context. And you will need to copy a lot of code there, because getBundle() is private. I will discuss possible modifications with the developers.
You can find an example here: https://github.com/fipro78/e4classbasedtranslation
Hope that helps you to solve your specific requirement.
AFAIK ResourceBundle.Control is used to load ResourceBundles. In the new Message Extension we use a custom ResourceBundle.Control to enable the loading of ResourceBundles in the OSGi context, and it is configurable via annotations.
AFAICS exchanging the ResourceBundle.Control will break any other use case supported by the new Message Extension.
The question is, why do you use a custom ResourceBundle.Control instead of creating a class based ResourceBundle? I haven't tried it yet, but maybe it is possible to create only the base ResourceBundle (without Locale information) and determine the Locale in another way than using getLocale().
But without knowing what you are doing in your custom ResourceBundle.Control, I don't know what to answer and what to suggest. Of course we could open the API for that, but as I said before, then every other plugin that makes use of the default implementation will fail.
Maybe you can give some hints on what you are doing exactly and I can show you a way to achieve your goal in another way.

What is the preferred way to read and write to a .properties file from within a Tapestry application

What is the preferred way to read and write to a .properties file from within a Tapestry application?
I have a Tapestry web application and at some point, I need to read (and write only once) some properties from a .properties file.
The application is deployed on a Glassfish server (3.1.2.2).
Where is the best location to write such a file and is there a preferred way on how to do it? It would be nice if it would be packed somewhere where the admins could access it without much troubles?
Ty in advance :)
Do you need to query and edit your own application configuration options? Have you thought about persisting it into a data base and discarded the idea for some particular reason? Maybe it would be a more consistent idea
We use Apache Commons Configuration and it works really well for us. It is very easy to configure as a service/Injectable Object and you can always use BeanEditForm for editing such a configuration.
Although this approach is best suited for localization, you can use messages for your problem.
First, create new .properties file in the same folder where your pages (.tml) are, or add them as a resource bundle. Also, name the .properties file same as the page. Then, you can inject the properties in your code like this:
#Inject
private Messages messages;
Then you can use built in methods .get() and .format() to read and write to properties.
Visit these to links to find more information about this:
http://tapestry.apache.org/localization.html
http://tapestry.apache.org/5.3.7/apidocs/org/apache/tapestry5/ioc/Messages.html

GWT client global configuration values

I need to store a few configuration parameters on the client side of my GWT app--I'm only using the client side of the framework. I just want to store things like an API access URL base.
Ideally, it would be nice if this were dynamically read, but I can live with having the values statically baked in on every compilation.
When scouring the web for answers, I kept running into all the deferred binding and locale management stuff. I don't care about any of that. I just want to set some property like api.url and read it from the Java code. Failing that, I'd like to set it in an external JavaScript file and read it in from the main generated JS code somehow. However, keeping it simple is an important goal; I don't want to go down the path of some Rube Goldberg-esque JSNI monstrosity.
Is there any means of accomplishing that with some sort of properties files, or a simple JSNI import mechanism? Or am I pretty much stuck with using a Constants-based configuration class (which still requires a recompile to bake in)?
This is what you're looking for: http://www.gwtproject.org/articles/dynamic_host_page.html
In order to escape from the compilations each time when configuration changed i would like to suggest the RPC call of configuration parameters in onmodule load.
In onsuccess you can assign those parameters to your Gwt static variables,those available throughout the Gwt code.
This may reduce the pain,you can change the parameters on serverside and deploy again,No Need To Compile each time for a single line change.
You can define a property on the module xml. Like this:
<define-property values="desenv, production" name="environment"/>
<set-property name="environment" value="production"/>

How is the Java Service Provide API supposed to work?

It seems like everybody has had an unpleasant brush with the Java Service Provider, that thing you can do with a file named like META-INF/services/com.example.Interface, but that nobody uses except for trying to load the right XML parser. I'm trying to work with a library that uses the Service Provider API, and trick it so that I can provide some runtime-extended classes (using cglib) that don't actually implement the interface but can be made to do so easily.
Basically, I think the steps I need to perform are:
Create a custom class loader that will respond to getResources(...) and return an "extra" URL
Also have that class loader hook getResourceAsStream(...) to return a list of the classes I am going to manipulate with cglib, when asked for the "extra" resource
Finally, have that class loader load those classes when requested
But here's where I get lost. For example, when the library tries to determine what implementers are out there, it calls getResources(...) which returns a bunch of URLs. But getResourceAsStream(...) doesn't take URLs, it takes "names". Names which seem to be classpath-relative, and therefore the same everywhere. So META-INF/services/com.example.Interface in has the same "name" as META-INF/services/com.example.Interface in their JAR, right? Except somehow this works with those blasted XML parsers...
Of course, all of this assumes they were smart/kind enough to call ClassLoader.getSystemClassLoader() rather than using ClassLoader.getSystemResources(...), ClassLoader.getSystemResourceAsStream(...), etc., as in the latter case there's no way to hook the ClassLoader and provide the faked file.
I guess in that case I could use BCEL to manipulate the class files when my code is being packaged by Maven, rather than waiting until runtime to do it with cglib?
The idea I described was along the right track. The mistake I made was in thinking that using ClassLoader.getResourceAsStream(..) to access the contents of the URLs. Instead, you should just URL.openStream().
Had I found it before posting, java.util.ServiceLoader (#since 1.6) provides some insight into how to do things correctly.

Implementing dynamic plugins in Java

I'd like to implement a dynamic plugin feature in a Java application. Ideally:
The application would define an interface Plugin with a method like getCapabilities().
A plugin would be a JAR pluginX.jar containing a class PluginXImpl implementing Plugin (and maybe some others).
The user would put pluginX.jar in a special directory or set a configuration parameter pointing to it. The user should not necessarily have to include pluginX.jar in their classpath.
The application would find PluginXImpl (maybe via the JAR manifest, maybe by reflection) and add it to a registry.
The client could get an instance of PluginXImpl, e.g., by invoking a method like getPluginWithCapabilities("X"). The user should not necessarily have to know the name of the plugin.
I've got a sense I should be able to do this with peaberry, but I can't make any sense of the documentation. I've invested some time in learning Guice, so my preferred answer would not be "use Spring Dynamic Modules."
Can anybody give me a simple idea of how to go about doing this using Guice/peaberry, OSGi, or just plain Java?
This is actually quite easy using plain Java means:
Since you don't want the user to configure the classpath before starting the application, I would first create a URLClassLoader with an array of URLs to the files in your plugin directory. Use File.listFiles to find all plugin jars and then File.toURI().toURL() to get a URL to each file. You should pass the system classloader (ClassLoader.getSystemClassLoader()) as a parent to your URLClassLoader.
If the plugin jars contain a configuration file in META-INF/services as described in the API documentation for java.util.ServiceLoader, you can now use ServiceLoader.load(Plugin.class, myUrlClassLoader) to obatin a service loader for your Plugin interface and call iterator() on it to get instances of all configured Plugin implementations.
You still have to provide your own wrapper around this to filter plugin capabilites, but that shouldn't be too much trouble, I suppose.
OSGI would be fine if you want to replace the plugins during runtime i.g. for bugfixes in a 24/7 environment. I played a while with OSGI but it took too much time, because it wasn't a requirement, and you need a plan b if you remove a bundle.
My humble solution then was, providing a properties files with the class names of plugin descriptor classes and let the server call them to register (including quering their capabilities).
This is obvious suboptimal but I can't wait to read the accepted answer.
Any chance you can leverage the Service Provider Interface?
The best way to implement plug-ins with Guice is with Multibindings. The linked page goes into detail on how to use multibindings to host plugins.
Apologize if you know this, but check out the forName method of Class. It is used at least in JDBC to dynamically load the DBMS-specific driver classes runtime by class name.
Then I guess it would not be difficult to enumerate all class/jar files in a directory, load each of them, and define an interface for a static method getCapabilities() (or any name you choose) that returns their capabilities/description in whatever terms and format that makes sense for your system.

Categories

Resources