Access to META-INF/weblogic-application.xml - java

I need to refactor an existing jar to work under weblogic 11c and 12c. The code requires full details of the java role to LDAP group mapping, as found in an ears META-INF/weblogic-application.xm. I seek a good mechanism to retrieve this information.
Some specifics:
The jar is not an EJB jar, and as the interface can't change, and I have no control over how it will be used in applications (it is a adrop-in replacement for an other library).
This means I can't inject the EJB context.
This also means I have no connection to the JMX mbean tree available (which would need configuration info)
I want something that works for multiple applications, all deployed as ears.
I want something that survives fastswap and exploded directory layout
I want something as future proof as possible
It needs to work both when called from WAR files as from EJB jar files
It needs to run under WebLogic 11c,12c, and be as future proof as reasonably possible
For now, i use this strategy:
Use getClass().getResource(myself) to retrieve an URL to my code
Drop the jar: prefix and associated ! markers
Scan upwards trough the directory tree, until we find a folder containing META-INF/weblogic-application.xml
If found -> read and parse./ Otherwise -> complain and crash
This seems to work, but I hope to discover a less hackish approach, either by accessing the xml file, or by querying the managed server which executes the jar (but without means to configure connection parameters)

Related

Do I need to define datastore-indexes in every microservice(module) which uses it or just in root application?

I work on an application with several microservices (modules). I defined datastore indexes in root application (which is containing just only those cfg files like datastore-indexes.xml and queue.xml etc). I see those indexes "serving" in console. [edit] so my fault i broken query earlier so question changes little. What is best strategy with mentioned cfg files in multi-module appengine app?
The datastore index configuration is one of the several app-level configurations, shared by all services/modules in the app and which can be deployed independently from the services themselves. In fact it's recommended to first deploy the indexes configuration, let GAE get those in Serving state (which may take a good while, depending on the number of entities that need to be indexed) and only after that deploy the app code needing those indexes.
For deployment on GAE purpose it doesn't really matter if the index configuration is located in a particular service or in the root of the application, as long as it's deployed from that location.
However the local development server may have trouble running a particular service without the index configuration in that server's directory - I suspect that's what causes you grief. To address this in the DRY spirit my preference is to have a master copy of the configuration file in the app root directory and symlinks pointing to it into each of the services directories.
Things get a bit more complicated because the Java GAE uses the datastore-indexes.xml configuration file while the other languages use the index.yaml file, with different formats. Java also supports the index.yaml file, but I'm not certain if that's equally well supported in the development server, IDEs and/or other local development tools.
If all your modules are Java-based you should be OK. But if you have a mix of languages you'll probably have to try to share an index.yaml equivalent.
If that doesn't work and you're forced to use both files, each symlinked into the respective language service dirs, you'll have to make sure the index configs in the 2 files are consistent, otherwise you risk breaking some of the services.
Potentially of interest: Can a default service/module in a Google App Engine app be a sibling of a non-default one in terms of folder structure?

Is there a typical way to handle separate configurations for different tomcat instances in a Java app?

Our system is split up into different environments, each one as a separate Tomcat instance.
Development (Windows)
QA: Accessed by our QA department (Linux)
Production: Live site, accessible to customers. (Linux)
Each of these environments rely on separate databases, and several other web services. This means we need to keep track of the various URLs, usernames, and passwords that are all different. Many of these settings are shared across several apps, so it would be ideal to have them all in one place to remove duplication.
Right now we have config files in the application itself. We use Maven profiles to fill in the different config settings when we build the app. But this is clumsy because we have to build a different WAR for each environment.
Where is a good place to store the config files so that we can deploy the same WAR file to each server?
I've done a fair amount of research on this already. But I haven't found an solution that completely makes sense to me yet.
Separate Config Directory
Define a directory to hold config files. Such as /opt/config on linux.
I like this idea, but how do I tell Tomcat where this directory is? I see references to context.xml, but every example I've seen puts the context.xml in the META-INF folder inside the WAR. Is there a way to configure this outside the WAR?
System Property to define environment
This involves setting a system property, and then using some sort of if/else or switching logic to load the appropriate config file. This seems workable, but a bit messy. But where/how do you set this property? I typically start tomcat with ./startup.sh. Do I add arguments to that command or is there another configuration somewhere?
JNDI
I don't think this is an option for us. Every tutorial I've looked at for this seems to be dependent on LDAP or something similar. To my knowledge we don't have that available to us, and it seems like too much overhead to get set up for only a half-dozen config files.
Use system property that refers to the location where your configuration file or directory is located. In this case you can manage different environment easily and no if/else logic is needed.
You application can have hard coded value of config file path, that will allow running application without any additional system property. The application however should fail to start if mandatory data is not found.
Concerning to partial sharing of data among environments.
You can split your data into several files by categories. Some files will be shared, some other different for different environments. You can even develop your own mechanism of references between data files.
However better approach is using some ready-to-use packages. For example Spring framework supports very flexible configuration mechanism. However if you already have Spring-less application introducing this framework for configuration only seems like an overkill. In this case take a look on Apache Commons Configuration package.
Worked with my team on this and we came up with what we feel is a cleaner approach. While every tutorial I found put the context.xml inside the WAR, it can also be placed in the conf folder of the Tomcat directory.
This works for us as all our servers are Tomcat based. So each server can have it's own context.xml which has a property pointing to the config folder on that particular server.

How to force my EAR files to just be deployed on an specific server?

I am developing an enterprise java application for a customer using J2EE technologies (JSF, EJB, Hibernate, etc). To avoid the customer to copy my .ear files and deploy them on another server (the AppServer is Weblogic), I am searching for a standard and secure method to bind my project output files into an specific physical server. This mean that I need my project output to be bound to a physical server at build time and the customer is just allowed to deploy then on an specific server.
Is there any standard method/library to do this or I should do it manually in my code using server identifiers?
I don't think that you will be able to 100% assure that a customer will be unable to copy, adapt and run your application to another server. First, an ear file is just a ZIP file, and classes inside are also easy to decompile and compile again, even if the EAR would be signed. So a lot of space to do some funny business :)
If you just wish to protect the customer from "accidentally" deploy your EAR on a second server, a first, easy and cheap step could be to link/insert the predicted host name (perhaps even the ip address) during the stage phase to a manifest or even java file (to make things more static). Then add an once initialized, later cached interceptor around all methods you would like to protect and check the local system (ie with InetAddress.getLocalHost()) against your preconfigured & linked host information. Still, very weak :/
If it's a MAVEN project you could add something to de settings.xml of the compilation server that allows things to run different on the configuration of the production system. Something like a different name for a datasource or something like that.

Java EE EAR shared location of read/write resources within clustered environment

Within a Java EE environment (happens to be WAS 6.1 but could be any application server) I need to place a XML file, which is a configuration file, so that I can read and write to it.
This needs to be available in a clustered environment so I am looking at using the class path to load the file.
I am thinking I can store this file in the EAR root, reference it in the manifest and then load and save it.
I have tried this approach by having my file in a JAR and making this available via the MANIFES and I can load the config file from the class path no problem using the following.
this.getClass().getClassLoader().getResourceAsStream("configFileName");
That loads the file that is in the JAR, which is fantastic. But if I want to edit this file, programmatically, I cannot access the JAR files location (the EAR root) it returns me an interpreted path like this:
/usr/IBM/WebSphere/AppServer/profiles/AppSrv01/installedApps/localhostNode01Cell/MyApp.ear/MyApp.war/TB_config.jar
That is not the correct location of the JAR the correct location is at MyApp.ear.
So the question is: how can I access and update (copy contents, create new, save, delete old) the JAR with my config file.
Or should I put the config file somewhere else?
What is the standard Java EE to make files that need read/write access available to WARs on a cluster?
Ok I have built a solution for this. It is more WebSphere based (our platform) but it is J2EE and I am suprised it was not mentioned. Basically I have used JMX to synchronise the nodes. The files are stored, and saved to, the deployment manager the nodes are then resynchronised using JMX calls and then the engines withing the applicaitons are restarted by calling servlets within the applications.
It works a dream
So #stacker, nodes are managed and the manager distributes files to the nodes.
The problem that you've hit is not unique. A lot of Java EE programmers can struggle with providing a "configurable" property file to administrators of a cluster. And the solution that you've chosen, well, has its limitations.
The problem with embedding a config file inside a JAR, is absolute path or the physical path of the file, in case you need to update it. If your container will not explode your EAR and WAR files, then placing the config file alongside the code is a bad idea - the administrator will have to deploy a newer version of the EAR/WAR/JAR. That is unless, of course, you can configure the container to explode the artifacts - WebLogic Server does this, I'm not sure about WAS.
There are several ways to resolve this problem:
Store the config file in a SAN that is accessible to all the nodes in the cluster via a 'canonical' path. That way, you could locate the file from any node in the cluster and update it. Remind yourself to restrict access to this directory. Although this sounds simple, it need not be - Java objects might have to be 'flushed' across nodes, once the configuration file has been updated. Moreover, you might have to cater to the scenario where property files can get edited outside the application.
Use a database. Much simpler and almost hasslefree, except that the Java objects might have to be flushed again.
Use a MBean. As good as a database, except that I haven't known a lot of people vouching for the MBean support in WAS. Also, I'm not really sure if object states can go haywire across a cluster, in this case.
You cannot write to an ear file, you should place the XML file in the DB as a text lob (large object).
Actually, as I am using WebSphere, it appears I can use the dynamic cache provided by the WebSphere deployment manager. The last chapter in the link below dicusses the use of the Dynamic Cache providing a shared object in a cluster. The configuration file is XML that is parsed as such by the engine (into a Document object) of the application and so is a Java object, thus it can be placed into the DistributedMap.
Looks like a clean solution. Thanks all for reading and your replies.
http://www.ibm.com/developerworks/websphere/library/techarticles/0606_zhou/0606_zhou.html

Tomcat parent webapp shared by configurable children webapps

Currently, we support many clients using the same web app, but each client has a different configuration for accessing their database, setting files etc. As the client list grows, updating the web apps is becoming increasingly arduous, and the duplication of resources is a waste of memory, file space, etc..
What we'd like to do is have a parent web app which is shared by all children web apps. Then have each child web app carry only files specific to them. When the child web app starts up, Tomcat loads the web app from the parent web app and then overrides any files defined in the child web app following an identical package structure.
We've been googling around and haven't found a ready or complete solution. Solutions we've looked at:
Tomcat common/share - could handle class and JAR files, but we don't see a way to handle static and JSP resources residing above the WEB-INF dir.
CATALINA_BASE appears to be more suited for running multiple instances of Tomcat which we'd rather avoid
A Maven possible solution, but we are not big fans of Maven, so would rather avoid it also.
Anybody have suggestions or ideas on how to solve this? If Tomcat configuration is not possible, what about a different application server (such as Glassfish) or a tool for doing dynamic file updated (such as OSGi, rsync). Would like to remove the resource duplication if possible.
Thank you.
There is no such thing as "parent" or "child" webapps. It's not part of J2EE spec and AFAIK it's not supported by any application server.
That said, your problem is twofold:
1) Having shared resources. This part is pretty easy assuming "resources" means static resources (images / CSS / javascript / etc...).
If they are truly shared (e.g. you don't need to have a separate version in some of your webapps), host them elsewhere (separate "common" webapp or put Apache in front of your Tomcat and host them there.
If you do need to have "local" versions of some of those resources you may be able to do some clever conditional URL rewriting or simply write a servlet that would check whether particular resource exists locally and, if not, take it from "common" location.
Precompile your JSPs so you only have to deal with JARs.
If your Tomcat instance only hosts your apps, you can indeed put your JARs in shared (or lib in the latest version); otherwise you can deploy them with each application .
2) Simplifying deployment. I'm not really sure what the big problem is here... It's rather trivial to write an Ant (batch, shell, what have you) script that would assemble and deploy WARs based on "common" and "per-app" directory structures.
Alternatively, you may want to take a look at using JNDI to severely reduce the number of files that have to be deployed (in theory, to a single context.xml for each application).
You can build parent-child hierarchy if you use Spring at your web-apps - Using a shared parent application context in a multi-war Spring application.
I.e. you can define all shared stuff at the 'parent' context and have 'child' contexts just to use it.
If all you had was setting file and configuration changes you could manage these through the context.xml and then you can point the docBase of each application context at a common directory for all the applications to share the same source.
the drawback to this is changes to the application will require a tomcat restart.
This does not however solve your problem if you want to override logic.
A option that I am exploring for a similar scenario is to move the client custom portion into ajax widgets / gadgets. Then have it be part of the configuration files to tell the application which version of the gadget to pull for which client.
you can review documentation for having applications share a docbase here http://tomcat.apache.org/tomcat-5.5-doc/config/context.html

Categories

Resources