Is it possible to keep referenced files inside the service itself? - java

I'm working on a jax-ws service in Eclipse. At some point, this service opens and uses a couple of XSLT stylesheets.
My question is, can you somehow import and keep these 2 files in the project itself, as you can with a library? For convenience' sake. I basically want my service to work as is, without having to go through the trouble of shipping the xslts along with the service but having to place them in different locations on the server, having to explain to people how and where they must go etc..
On a related note, how come when I make new File("D:\x.xslt");, the service looks for it in "C:\Users\Tudor\Desktop\eclipseJ2EE\eclipse\D:\x.xslt"? As in, *eclipse_path*/*fileName*. I would have understood, if it looked for the file in the root of the apache tomcat server; but not the installDir of eclipse... Anyway, how do I change that behaviour?

You can store the xslt file within your source classpath and load it via the Classloader.
If you are using Spring you can also use the ResourceLoader to load resources.
Its rarely a good idea to use File instances with relative paths directly, since within different server environments the base directory often differs.
Hope this helps.

Related

Manage a WebSphere shared library without OS access

We have two JEE applications in our WebSphere 8.5.x environment that both depend on a common JAR. Without going into too much detail, suffice it to say that the JAR needs to be set up as a shared library and attached at the server level. I would like to know how to manage this shared library without having OS access to update the file, instead updating through the WAS console.
As I understand it, for a WAS shared library you need to have placed it somewhere on the OS before you can set up the shared library reference since you have to provide the path to the e.g. JAR file.
I would like to be able to complete a deployment, replacing all binaries including the shared library, without having to remote into the OS and update the JAR on disk. I would prefer a method where someone using the WAS console could update the shared library on disk much like they can upload a new application.
I've looked into a WAS "Asset" (WAS Console -> Applications -> Application Types -> Assets), with the hope that this would allow me to manage and upload the JAR file through the console. I am able to upload the JAR as an asset and can see it when it lands on disk, but I am not understanding what to expect from this and am loathe to use this without knowing everything that's going on.
I see the "Asset binaries destination URL" option but that doesn't seem to do anything. I can put anything I want in that field when importing the asset and it always goes to "${APP_SERVER_ROOT}/config/cells/${CELL_NAME}/assets/${ASSET_NAME}/aver/BASE/bin/" on the management node, not the worker node. This location is also the configuration repository, and I get a funny feeling mapping directly into a repository location like this.
I could, I suppose, create the shared library with a path directly into that location but I am concerned that I'm missing something and that this isn't a good idea.
Does anyone have any insight into this they could share?
To use a shared library with WebSphere you can go to Environment > Shared Libraries and upload/configure a shared library on that page (including choosing which applications you want to associate with the shared library).
For full info, see IBM's doc: Creating shared libraries
You could try to use Business level applications and upload jars as asset, specify them as shared libraries and map during application installation (however I've never done that and it might not work). Check the following links:
Business level applications
Creating business-level applications with the console

Is there any native mechanism whereby we can override classes in an existing deployed Struts2 app?

Specifically, if we have an original .war file deployed in a application server, can one deploy a .war which provides different implementations of classes in the original file without having to modify the base code to support this?
Edit. I've formulated the problem wrongly, it's actually simpler I think. We want to expose actions from two distinct WARs in the same base path, rather than a different path for each WAR. Can it be done at the container configuration level?, or do you recommend employing something like URL rewriting?
Not easily. Generally, a deployed WAR becomes a discrete webapp within a Java EE server, and it gets its own classloader. Your second deployment will get another classloader, and although they will definitely share some ancestry, it won't be possible to reimplement things from the other WAR - your second deployment won't be able to 'see' it, because of the way the classloaders are chained together.
It is possible to rewrite running classes using a Java agent, although this is nontrivial. You can transform (rewrite incoming) classes and you should be able to rewrite live (instantiated) classes, although the problem there is that there may be objects on the heap using the old and new code.
Class rewriting is how Eclipse's Hot Code Replace works, and also how JRebel's fast redployment solution functions.
You might be able to use an AOP system like AspectJ if you really want to pursue this - but it sounds like you're trying to solve a build or deploy problem, rather than a problem where AOP would be a more fitting solution.

Is it possible to have multiple cxf.xml files to configure separate parts of the system?

It seems interesting, that nobody asked this before. I have some "basic"-questions about the configuration of CXF Clients.
We have a Tomcat running our application. This application needs to communicate with a WebService. The implementation of the client is done with CXF, and this implementation is packaged in a JAR-File. Lets say "ws-client.jar". It is possible and desirable, that there are other implementations of clients for other webservices, also using CXF. And each WS-Client should be packaged in its own JAR-File. So at the end I'll have our application WAR, containing all other ws-client*.jar I need.
bigApplication.war:
WEB-INF/lib/ws-client.jar
WEB-INF/lib/ws-client2.jar
WEB-INF/lib/ws-client3.jar
...
WEB-INF/classes/**/*.class
And now the question: Where can/may I put the cxf.xml? Can I put a configuration file in each ws-*.jar? Can a put in addition another in the war file? Or only one cxf.xml file must exist? Which path in the archive is the best?
By now I just copy a configuration file in tomcat/webapps/bigApplication/WEB-INF/classes/cxf.xml (probably also not the best place for it). The problem is, I need to do that every time I deploy the application. And I want actually only to configure ws-client.jar, and not all CXF-WS-Clients. So I want to configure things as specific as possible, and in the write place.
Any answer is welcome, also Links to the right information, which I didn't find.
[UPDATE]
As it is a somehow long question, here the questions in the post together:
Can I put a cxf.xml file in a jar-archive?
Can more than one cxf.xml file exists per application? One in each relevant .jar file?
Where is the best path in a jar-file to put the cxf.xml?
[/UPDATE]
Normally, each "part" of the application would have it's own xml files (likely not called cxf.xml). Something like "cxf-client2.xml" or similar. There would then be a "main" cxf.xml for the war that would import the various other xml files.

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

Where should a Java web application store its data?

My Java web application (myapp.war) ist deployed by placing it into the webapps direcotry on Tomcat on Ubuntu 10.04.
This application needs to save some data in files. But the user, which is running Tomcat (tomcat6) has no write access to the home directory /usr/share/tomcat6/ and no write access to the current working direcotry /var/lib/tomcat6/, since both belong to root.
So where should a web application store its data? I hope it is not the extracted archive in the webapps direcotry. This one could be deleted very easily by accident. And Tomcat can be configured, not to extract .war files. Then there would be no extracted direcotry.
Perhaps /var/lib/tomcat6/ should belong to user tomcat6 ant this is a bug in Ubuntu?
If the files need not persist longer than the life-cycle of the servlet context, the servlet container provides a private temporary directory for each servlet context, specified by javax.servlet.context.tempdir attribute.
See Servlet Specification 2.3, Chapter 3 Servlet Context
3.7.1 Temporary Working
Directories
The convenience of a temporary
storage directory is required for each
servlet context. Servlet containers
must provide a private temporary
directory per servlet context and
make it available via the
javax.servlet.context.tempdircontext
attribute. The object associated with
the attribute must be of
type java.io.File
Answering his own question, Witek stated /var/lib/tomcat6/webapps/ is writable -- at least on his installation of his version of Ubuntu. On my RHEL 5.2 system /var/lib/tomcat<X> doesn't even exist, so there is no webapps subdirectory writable or not, which leads to my answer.
Q: Where should a Java web application store its data?
A: Wherever you've configured it to store its data.
Make the location configurable, in web.xml as a <context-param> or in a myApplication.properties file.
I can put it where I want on my box, the SysAdmins can put it where they want on the production system.
You can change your mind later.
You don't need symbolic links (which have magically disappeared on me before, breaking the system.)
You can have several sets of test data, and just point the configuration at whichever one you want.
You can put it wherever there's disk space.
You are going to change your mind later.
I think it depends on what kind of data you are dealing with. Most of the time, data goes into the database simply because it is fast and easy to perform a CRUD. If you want to store localized user configuration and you don't care how portable it is, perhaps you can store under user.home, I did that for one of my projects and that works fine. All that being said, I really don't think there's any best practice on this and database seems to be the most obvious choice because you can do whole lot of different tasks against it, and most of them are free to begin with. :)
I found the solution on Launchpad. /var/lib/tomcat6/webapps/ is writable. This means, that the following works:
File myFile = new File("webapps/myfile.txt");
I haven't seen any specific guidance on where you should store that kind of data locally - probably because you'd normally store that kind of data in a database.
When I need to store quick-and-dirty data like that, I store it on a filesystem specifically for that data, to isolate it from other areas where it might get caught up in other activity. Haven't had any issues with the approach so far. Also, if it's important, make sure you store it somewhere where you're backing it up :)

Categories

Resources