How do I move source code to a another package/group ID?
The trick here is changing the package name in multiple places. It is easiest to let Eclipse handle most of it (via Refactor->Rename).
- In Eclipse, change the package name from the Package Explorer by clicking on it, then pressing Alt-Shift-R.
- This will also change the import line in your source code AND your directory tree to match.
- If you don't use Eclipse's Rename, you will have to do these steps yourself.
- Don’t forget ALL your source files, including src/test/java and src/main/resources.
- Change the implementation attribute in ComponentFactory.xml.
- Change the group ID in the pom.xml.
- Change the Private-Package section of the POM.
- Do NOT change the aspire.framework line.
- Run the command: mvn clean install
- You may seem some new errors about missing dependencies (that were in the package you moved away from); solve those by adding the old package as a dependency in the POM.
Note that your JAR may still include a com.searchtechnologies section AS WELL AS your new path because Aspire includes com.searchtechnologies.aspire.framework in every distribution.
Now the project that uses the above, JAR needs to be adjusted for its new location:
1. In the Aspire config file that references your component, change the factory name; for example:
2. In the POM for the enclosing project, find the dependency block for your component and change its groupId:
3. In the distribution.xml file for the enclosing project, make sure that there is a dependencySet for the new package:
JUNIT returns "Class Not Found" error
Things to try:
- Run a "Project/Clean..." command (within Eclipse) on your project.
- Right-click on your component project and do "Configure Build Path...", then go to the "Order and Export" task and make any dependent projects are moved to the top, before the Java System Libraries.
IE may try and turn our XML files into feeds
Try to avoid using metadata tags which start with "<rss" or "<feed", e.g., <feederLabel>.
Basically, IE looks for certain tags at the beginning of a random XML file to determine if it's an RSS feed. If it is, it may do something special with it.
When using an RSS 2.0, 0.91, or 0.92 feed, the HTTP Content-Type header should be “text/xml”:
Because this is a generic content-type, IE7 will scan the first 512 bytes to look for the “<rss” string that indicates that it is a feed. If the string is found, the file is considered a feed, and the feed preview is shown to the user. For example, this is a RSS 2.0 feed for the IE blog, and IE7 determines that it is a feed because of the highlighted string.
IE may then report that the XML file can not be parsed as an RSS feed (or some such error).
How do I solve class loading errors when running my third party code in OSGI?
When running under just the component test bench, everything worked fine, but when running under the application test bench, a third-party JAR is unable to locate its own properties file.
Sometimes, third-party JARs use wacky methods for loading classes. In the case of the ROME libraries, do the following under OSGi in order for the ROME JARr to locate its own properties files:
How to load a class from an external JAR file
You need to create a classloader containing the current classloader and the JAR file you wish to use. Try the following code:
You can then either load the classes directly from the loader:
Or set the current thread's class loader to be the one created:
Why am I getting an infinite loop when reading my component's configuration?
I ran into a subtle infinite loop, which I'd like to share with you.
First, my XPath for extracting components from a component-manager configuration is this:
And my system XML was this:
The infinite loop was this:
- Start the system manager and get /config/components/component.
- Start all of these components.
- Now, the pipeline manager needs to start all of its sub-components. So what XPath does it use? Well, it's: /config/components/component
What happened is that the pipeline, when it got the list of components, because of the leading "/", it actually accessed the components from the top-level of the configuration file, not the components nested within the pipeline-manager's configuration section.
And so, it started all of the components, which meant that it started another copy of itself! (When it then went again to /config/components/component, got the top-level components again, and then started another copy if itself again, etc. etc.)
The Moral Of The Story:
When accessing your configuration elements with XPATH, do not use a leading "/". If you do, you will access the configuration of the system manager all the way at the top.
You will be passed an "element" as your configuration, which is a <config> element nested within the overall system configuration file. If you are using XPaths to extract information from the element, a leading "/" will go all the way to the top.
Note that none of this affects how the digester works. You should still use a leading "/" for simple-digesting.
To fix the problem, change your XPATH to simply: components/component
Note there is no need to prefix it with "config", since we are already "inside" the config node.
Don't Create Your Stage Inside of Another Maven Project
This will create unnecessary and destructive <parent> tags inside your stage's pom.xml file. If you discover these, just delete the entire <parent> tag.
It is best to use the archetype to create the stage directly inside your Eclipse project.
Why do my bundles sometimes get a timestamp when I use "mvn assembly:assembly"
Under certain circumstances, the bundles copied to the output directoy are named with a timestamp:
You can solve this by adding an outputFilenameMapping (line 2) to the distribution.xml file:
How do I abort / terminate a job?
Call job.terminate(). This will set a flag which causes the job to be terminated once the current stage completes. See Terminating Jobs for more details.
Strange class issues when running bundles
I got a stange class loadeder issue when loading a component
It turned out to be a missing import package. Adding org.osgi.util.tracker to the <Import-Package> of the pom solved it.
I've also seen this error:
Again, this was a missing import. I cleaned up the pom and added javax.xml.namespace to the <Import-Package>
One error not caused by the pom:
This was because of a comment in an XML file being read by the following code:
The only solution at the moment is to remove the comment.
Calling Components from other Components
See Accessing Other Components for details on how to programatically access one component from another.
Suppose you have a situation where one Aspire component needs to call another component, for example where the RDBFeeder needs to call the RDB connection pool. You need to be careful when declaring the import and export packages in the components pom file and the component dependencies.
Basically, OSGi acts as a broker between components which need to access certain java packages, and components which supply these packages to other components:
In order for OSGi to know how to “wire things up”, it needs to know (through the <Export-Package> and <import-Package> tags in the POM files, exactly what java packages (not, not classes, but entire packages) are available to other components (<Export-Package>) and which ones are need to be accessed from other components (<Import-Package>).
Also, we would strongly recommend that you separate out the methods of your classes, which need to be exported, and include these in a Java “Interface” – and then put this interface into a separate java package – to better control the interface between your packages. This will help organize your thoughts about exactly how packages should communicate to each other. See aspire-rdb and the RDBMSConnectionPool (inside the com.searchtechnologies.aspire.rdb package) for an example.
Your caller bundles should also include a dependency of your called bundle in the pom file.
Typically if you get something wrong you'll see an exception like:
At the point at which you try to access the component:
If you still have issues, other things to try:
- If you're using release 0.3 or below, make sure the called bundle is listed earlier in the <bundles> tag than the caller:
If you're using version 0.4-SNAPSHOT or later, this shouldn't be an issue as Aspire will automatically load the dependent bundle first.
- Open up the JAR files for both bundles with WINRAR and check the directories to ensure that the one which is supposed to have the com.searchtechnologies.cpatools.Logger file does have it (the called) and that the one which is not supposed to have it (the caller), in fact does not have it.
- Also open up the JAR files and check the MANIFEST file to see if the imports from the <Import-Package> and <Export-Package> elements are correctly copied into the MANIFEST file.
Pom File Dependencies
When creating components, you'll often need to reference other Aspire components or third-party JAR files. In order to do this, you'll end up with one or more dependencies in the pom file, similar to this:
You should have added these in order to make the code compile. If you didn't, and you added JAR files directly to the build path in Eclipse, then shame on you. You'll regret it later.
However, making it compile is not the same as getting it to run within Aspire.
The first thing to note is that only one of the dependencies in the fragment above has the <scope> tag. If you don't specify this, the scope defaults to compile. The scopes are described below:
- compile - Include the third-party JAR in my component (i.e., the bundle JAR file will contain the third-party JAR file).
- Note: In the example above, "aspire-simplefeeder" behaves like a "third-party JAR." It will actually be included in your component just like any other JAR from someone else.
- provided - The packages I need will be provided by this other aspire-X component, which I have specified as "provided" (i.e., the bundle JAR file will NOT contain the third-party JAR file).
- test - This is only needed for testing.
Aspire (from 0.4 onwards), when attempting to load a component, assumes any provided dependency (with exceptions such as aspire-application, aspire-services, and org.osgi) is a Full Aspire Component which must be pre-loaded before the current component can be loaded. The Aspire built-in dependency loader is only for complete Aspire components (they must be specified as <packaging>bundle</packaging> in their POM). It will not work for ordinary JAR files. This is by design. Ordinary JAR files must be included in your component (as a compile-time dependency), or they must be exported by another component.
In versions 0.3 and earlier, you need to ensure that a dependent bundle is loaded first by ensuring the file appears first in you <bundles> tag. Again, third-party JAR files must be included in your component (as a compile-time dependency).
Enabling JMX Console to investigate memory issues with Felix
If you experience memory issues or JVM core dumps you can enable JMX on Felix and then connect using JConsole.
Just add the following parameters to the JAVA_OPTS in the start up script:
Restart Aspire and then use JConsole to connect to port 9999.
Aspire and Permgen Memory Issues
The permgen is where the JVM keeps the actual classes (not the instances, just the "boiler plates"), including fields, method names, etc.
Given how OSGI works, exposing some classes as "private" within the bundle and other as "public", i.e., available to other bundles, then the classloader(s) could have different dynamic classes for what could be considered copies of the "same" class (which may or may not be true in reality, because they could be different versions of it, with even different functionality).
Hence, OSGI will tend to fill more easily this memory.
The more evident example today is the JMS Feeder; which uses reflection on its implementation, thus indirectly using more of this memory.
All in all, it is a small price to pay (increasing this memory) for all the capabilities we get from the OSGI framework.
Therefore, it is important that we monitor this memory usage. It can be checked using the JConsole.
For setting and/or changing the permgen size, just add/change the MaxPermSize parameter to the JAVA_OPTS in the start up script. An example where we set the size to 256m is below:
Given its nature, permgen is not garbage collected.
Pipeline manager thread pool and queue are full, but all processing is stuck
In some rare cases, an error in the configuration of pipeline managers and branches can cause a deadlock. To prevent that, be sure that you are not branching sub-jobs to the same pipeline manager doing the branching.
Pipeline Manager A: XMLSubjobExtractor -> PrintToFile
Where XMLSubjobExtractor branch is configured to send jobs to Pipeline Manager A. This will almost certainly cause a deadlock.
Pipeline Manager A (parent jobs): XMLSubjobExtractor
Pipeline Manager B (sub-jobs): PrintToFile
Where XMLSubjobExtractor branch is configured so it sends jobs to Pipeline Manager B.
Notice that the same may happen wherever you have a branch configuration. So be careful when setting the destination of your branches.