Eclipse tracing.What is best practice?How to get instance of DebugTrace? - java

I'm working on RCP aplicattion, that works on Eclipse 4 platform(Luna). I neeed to find out how to get instance that implement tracing inside my Application. I found out the following ways
-
Using ILog interface, that can be get via Platform.getLog call. ILog has good point. It prints to .log file that located in .metadata, but
it get IStatus object as parameter. So for logging each line to log I have to created new instance of Status object. And it cannot put automatically information about caller like class name etc.(like Log4j, LogBack)
I found interface DebugTrace that provide good functionality for traicing. It can be obtained via DebugOptions inerface(DebugOptions.newDebugTrace()). To my regret I could not find appropriated way for getting instance of DebugOptions

To use DebugTrace, add this to the plugin Activator:
private DebugTrace tracer = null;
public static DebugTrace getTrace()
{
return plugin.tracer;
}
public void start(final BundleContext context) throws Exception
{
...
final Hashtable<String, String> properties = new Hashtable<String, String>(4);
properties.put(DebugOptions.LISTENER_SYMBOLICNAME, "org.eclipse.ui.trace"); //$NON-NLS-1$
context.registerService(
DebugOptionsListener.class.getName(),
new DebugOptionsListener()
{
#Override
public void optionsChanged(DebugOptions options)
{
tracer = options.newDebugTrace(context.getBundle().getSymbolicName());
}
}, properties);
You will need to add a .options file to the plugin project which will contain your logging options:
# Editor-related tracing
com.acme.atf.app/trace/editor=false
#Start-up tracing
com.acme.atf.app/trace/startup=true
org.eclipse.core.jobs/jobs=true
org.eclipse.core.jobs/jobs/beginend=true
org.eclipse.core.jobs/jobs/errorondeadlock=true
Hope this helps...

Related

How is the method run(T var1, Environment var2) in Application class called in Dropwizard?

Within a Dropwizard application,
the abstract run method in the Application class is usually overriden in the main service with something like this:
#Override
public void run(MyServiceConfiguration configuration, Environment environment) throws Exception {
// application logic
}
I tried tracing the execution logic and couldn't figure out where/how that method is being called. Can someone point me in the right direction?
Let's start at the beginning, when you run your Dropwizard application as a server you're giving the server command on the command line interface (CLI).
The example the documentation gives is:
java -jar target/hello-world-0.0.1-SNAPSHOT.jar server hello-world.yml
In io.dropwizard.Application (which you normally extend) we can see that the following commands are added to the bootstrap:
protected void addDefaultCommands(Bootstrap<T> bootstrap) {
bootstrap.addCommand(new ServerCommand<>(this));
bootstrap.addCommand(new CheckCommand<>(this));
}
In this case this is the instance of your class extending Application, which is given to the ServerCommand.
Then the run method in the same class will parse the CLI:
public void run(String... arguments) throws Exception {
final Bootstrap<T> bootstrap = new Bootstrap<>(this);
addDefaultCommands(bootstrap);
initialize(bootstrap);
// Should be called after initialize to give an opportunity to set a custom metric registry
bootstrap.registerMetrics();
final Cli cli = new Cli(new JarLocation(getClass()), bootstrap, System.out, System.err);
// only exit if there's an error running the command
cli.run(arguments).ifPresent(this::onFatalError);
}
When we follow cli.run(arguments).ifPresent(this::onFatalError); we end up in io.dropwizard.cli.Cli#run. In this method the command is parsed, and since we specified server it will find that command by name and execute it:
public Optional<Throwable> run(String... arguments) {
...
final Namespace namespace = parser.parseArgs(arguments);
final Command command = requireNonNull(commands.get(namespace.getString(COMMAND_NAME_ATTR)),
"Command is not found");
try {
command.run(bootstrap, namespace);
...
The server command will be an instance of io.dropwizard.cli.ServerCommand, which extends io.dropwizard.cli.EnvironmentCommand.
And it is in the EnvironmentCommand that we can see that your requested Application.run(...) method is executed:
protected void run(Bootstrap<T> bootstrap, Namespace namespace, T configuration) throws Exception {
...
bootstrap.run(configuration, environment);
application.run(configuration, environment);
run(environment, namespace, configuration);
}
This line specifically:
application.run(configuration, environment);
The T configuration is added via the base class of EnvironmentCommand, which is io.dropwizard.cli.ConfiguredCommand.
All code is taken from Dropwizard version 2.1.0

Failed to load the sqljdbc_auth.dll when running multiple JBehave Stories via Maven

I'm working with a Maven project that has three modules:
Database
Module that contains a JBehave Story (Story .java, .story, and steps .java file)
Another module that contains a JBehave Story (Story .java, .story, and steps .java file)
Both of the modules that contain a JBehave Story have the same type of .java file that runs the .story file and steps. Below is the .java file both modules have (but have different names for test purposes):
public class FirstStories extends ConfigurableEmbedder {
private SqlDataSourceProvider dataSourceProvider = new SqlDataSourceProvider();
private final CrossReference xref = new CrossReference();
private Context context = new Context();
private Format contextFormat = new ContextOutput(context);
private ContextView contextView = new JFrameContextView().sized(640, 120);
private ContextStepMonitor contextStepMonitor = new ContextStepMonitor(context, contextView, xref.getStepMonitor());
public FirstStories() {
System.setProperty("jbehave.test", "true");
configuredEmbedder().embedderControls().doGenerateViewAfterStories(true).doIgnoreFailureInStories(false)
.doIgnoreFailureInView(true).doVerboseFailures(true).useThreads(1).useStoryTimeouts("5m");
configuredEmbedder().useEmbedderControls(new PropertyBasedEmbedderControls());
}
#Test
#Override
public void run() throws Throwable {
Embedder embedder = configuredEmbedder();
try {
embedder.runStoriesAsPaths(storyPaths());
} finally {
embedder.generateCrossReference();
}
}
#Override
public Configuration configuration() {
Properties viewResources = new Properties();
viewResources.put("decorateNonHtml", "true");
viewResources.put("reports", "ftl/jbehave-reports-with-totals.ftl");
return new MostUsefulConfiguration()
.useStoryReporterBuilder(
new StoryReporterBuilder()
.withDefaultFormats()//.withViewResources(viewResources)
.withFormats(contextFormat, CONSOLE, TXT, HTML_TEMPLATE, XML_TEMPLATE).withFailureTrace(true)
.withFailureTraceCompression(true).withCrossReference(xref))
.useStepMonitor(contextStepMonitor);
}
#Override
public InjectableStepsFactory stepsFactory() {
return new InstanceStepsFactory(configuration(), new Steps(dataSourceProvider));
}
private List<String> storyPaths() {
String filter = System.getProperty("story.filter", "**/*.story");
return new StoryFinder().findPaths(codeLocationFromClass(this.getClass()), filter, "**/failing_before*.story");
}
}
The .story file is very straightfoward and only has one scenario:
Meta:
Narrative:
As a user
I want to perform an action
So that I can achieve a business goal
Scenario: Test scenario
Given nothing
When I do nothing
Then nothing happens
The steps file only contains one no-op method just to get everything working properly.
When running both JBehave tests via maven, the first story will run just fine. However, when starting up the second story, the following message appears, and the test shortly fails (I can run the second story on its own without issues, only when it runs after the first story):
WARNING: Failed to load the sqljdbc_auth.dll cause : Native Library C:\Windows\System32\sqljdbc_auth.dll already loaded in another classloader
java.sql.SQLException: An attempt by a client to checkout a Connection has timed out.
Is there something I am forgetting to do during my story's run() method to make sure everything is properly destroyed after the story is finished running, so the next story can run correctly without problems?

How to call one of the methods in my Bundle-A jar file after it has been installed into OSGi container

I have recently started working on OSGi framework. I have one bundle named Bundle-A. I want to call one of the methods in Bundle-A jar from my main application.
I have loaded and installed Bundle-A from my main application. Below is my code for my main application where I am installing Bundle-A.
private void initializeModelFramework() {
try {
FileUtils.deleteDirectory(new File("felix-cache"));
FrameworkFactory frameworkFactory = ServiceLoader.load(FrameworkFactory.class).iterator().next();
Framework framework = frameworkFactory.newFramework(new HashMap<String, String>());
framework.start();
BundleContext bundleContext = framework.getBundleContext();
modulesNameVersionHolder.put("Bundle-A", "1.0.0");
List<Bundle> installedBundles = new LinkedList<Bundle>();
String basePath = "C:\\ClientTool\\LocalStorage";
for (Map.Entry<String, String> entry : modulesNameVersionHolder.entrySet()) {
String version = entry.getValue();
final String filename = name + Constants.DASH + version + Constants.DOTJAR;
final String localFilename = GoldenModulesConstants.FILE_PROTOCOL + basePath+ File.separatorChar + filename;
installedBundles.add(bundleContext.installBundle(localFilename));
}
for (Bundle bundle : installedBundles) {
bundle.start();// this will start bundle A
}
// After starting the Bundle-A, now I need to call one of the methods in Bundle-A
for(int i=0; i<=10; i++) {
//call processingEvents method of Bundle-A class GoldenModelFramework
}
} catch (Exception e) {
e.printStackTrace();
}
Now the Bundle-A has been started up. Below is my Activator class for Bundle-A.
public class Activator implements BundleActivator {
private static final String BUNDLE_VERSION_KEY = "Bundle-Version";
private static Logger s_logger = Logger.getLogger(Activator.class.getName());
#Override
public void start(BundleContext context) throws Exception {
final Bundle bundle = context.getBundle();
final String bundleName = bundle.getSymbolicName();
final String bundleVersion = (String) bundle.getHeaders().get(BUNDLE_VERSION_KEY);
System.out.println(bundleName+" - "+bundleVersion);
}
#Override
public void stop(BundleContext context) throws Exception {
System.out.println("Bye.!");
}
}
And below is the class I have in Bundle-A jar. I need to call processingEvents method from my above main application code as soon as Bundle-A has been started.
public class GoldenModelFramework {
private static final Logger LOGGER = Logger.getLogger(GoldenModelFramework.class.getName());
private static final long checkingAfterEveryXMinutes = 15L;
public GoldenModelFramework() {
// following the traditions
}
public static void processingEvents(final String item) {
for (BundleRegistration.HolderEntry entry : BundleRegistration.getInstance()) {
final String response = entry.getPlugin().process(item);
System.out.println(response);
}
}
}
I am not sure what's the right way to do it? I know one way is add the dependency of this Bundle-A in my main application pom.xml file as I am using maven based project. But I don't think so that's the right way to do it. Because ultimately, I am going to have some more bundles so there should be some other way around for this which I am not aware of.
Should I am supposed to use ServiceListener or ServiceTracker here? Any simple example basis on my code will help me understand much better. Thanks.
I hope the question is clear enough. I am trying to call one of the methods in Bundle-A after it has been loaded up and installed.
You have several choices:
Import the package dynamically
You can use DynamicImport-Package instead of Import-Package. In this case bundle-A does not have to be active when the main bundle starts. Although this works I do not recommend this solution as I do not like DynamicImport-Package. In this case of course bundle A has to be a dependency of the main bundle.
Using reflection
You can call the method you want with reflection like the following (draft example):
Class<GoldenModelFramework> clazz = bundleA.loadClass("GoldenModelFramework");
Method m = clazz.getMethod("processingEvents", String.class);
m.execute(null, myParam);
This is a bit better, however this solution is still a bit foggy, I would not say this is a clean code.
Using interface and OSGi service
The cleanest way would need a bit of refactoring. In this case you should create an interface and in the Activator of bundle A you should register a service based on that interface. In the main bundle you should use a service tracker to catch that service and call the method on it.
In case you really want to make your method processEvent static, the registered service object (that is based on the interface) should simply call the static method inside.
Not to have the necessity to add bundle A as a dependency to the main bundle the interface should be taken into a third bundle that is the dependency of both, the main and A bundle.
Although this solution seems to be the most complex I would suggest this one.
An example:
Create an interface and put it to a new bundle like goldenframework-api.
public interface GoldenModelFrameworkOSGi {
void processingEvents(final String item);
}
The goldenframework-api will be a dependency of main bundle and bundle-A. The main bundle will use it, while bundle-A will implement it.
Here is how bundle A implements it:
public class GoldenFrameworkOSGiImpl {
public void processingEvents(final String item) {
GoldenModelFramework.processEvents(item);
}
}
Create an Activator class in bundle-A (I will leave out your code in that activator to have less typing):
public class Activator {
private ServiceRegistration goldenFrameworkSR;
#Override
public void start(BundleContext context) {
goldenFrameworkSR = context.registerService(GoldenFrameworkOSGi.class, new GoldenFrameworkOSGi(), new HashTable());
}
#Override
public void stop(BundleContext context) {
goldenFrameworkSR.unregister();
}
}
As you know the code of Bundle-A you can cheat a bit. When bundle-A is in Active state you can be sure that the service you need is registered. However, in the future you should think in working based on events (like using a ServiceTracker). I mean this will be a bad practice :) :
ServiceReference sr = context.getServiceReference(GoldenServiceOSGi.class);
GoldenServiceOSGi gs = context.getService(sr);
gs.processEvents(...);
context.ungetService(sr);
This might solve your problem for now and you can continue with your work. However, please consider reading a book like "OSGi in Action" to have a feeling about OSGi bundle and service lifecycles so you may re-design your framework.

How to check if a Java ResourceBundle is loadable, without loading it?

I would like to check the existence of a ResourceBundle without actually loading it.
Typically, I'm using Guice, and at initialization time, I want to check the existence, while at execution time, I want to load it. If the bundle doesn't exist, I want an early report of the inexistence of the RB.
If it was possible to get the ResourceBundle.Control instance used for a specific ResourceBundle, I would have no problem getting the basic information to build the actual resource name (using toBundleName() and toResourceName()), but it is not the case at that level.
Edit:
Ok, I found the way to do it. I'll create a ResourceBundle.Control that is extensible (using a custome addFormat(String, Class)) to store all the bundle formats, then use another method of my own to check all possible file names for a specific locale (using Class.getResource as indicated here below).
Coding speaking:
class MyControl extends ResourceBundle.Control {
private Map<String,Class<? extends ResourceBundle>> formats = new LinkedHashMap();
public void addFormat(String format,Class<? extends ResourceBundle> rbType) {
formats.put(format, rbType);
}
public boolean resourceBundleExists(ClassLoader loader, String baseName, Locale locale) {
for (String format: formats.keySet()) {
// for (loop on locale hierarchy) {
if (loader.getResource(toResourceName(toBundleName(baseName, locale), format)) != null) {
return true;
}
// }
}
return false;
}
}
If the default bundle must exists you can do:
Class.getResource("/my/path/to/bundle.properties")
and it will return an URL to the file or null if it doesn't exists.
Of course use the correct class or classloader if you have many.
EDIT: if you have resources as classes you have to check also
Class.getResource("/my/path/to/bundle.class")
In Java 6 you can store resource bundles in XML. I don't know how ResourceBundle class lookups this resource, but I bet it's in the same way.
You can load the bundles, thus making your checks, and then call ResourceBundle.clearCache() so that they are loaded again next time.
This happens once (at initialization time), and it isn't such a heavy operation, so it won't be a problem.
Or you can simply try to find whether a resource is present on the classpath. For example the fallback .properties file, or the properties file for your default locale.
Finally, after having a look at the code for ResourceBundle.Control, you have the option to do what they do in the newBundle() method.
Something like this, maybe
ResourceBundle bundle;
public PropertiesExist() {
String propsFile = "log4j";
String propsPath = this.getClass().getClassLoader().getResource(".").getPath();
File f = new File(propsPath, propsFile + ".properties");
if(!f.exists()){
System.out.println("File not found!!!!");
System.exit(-1);
}
bundle = ResourceBundle.getBundle(propsFile);
System.out.println(bundle.getString("log4j.rootLogger"));
}
public static void main(String[] args) {
new PropertiesExist();
}
This will look for the logging file, log4.properties, if not found program will exit

How do I get the OSGi BundleContext for an Eclipse RCP application?

I have just gotten started with an Eclipse RCP application, it is basically just one of the provided "hello world" samples.
When the application boots up, I would like to look at my command-line parameters and start some services according to them. I can get the command-line parameters in IApplication.start:
public Object start(IApplicationContext context) {
String[] argv = (String[])
context.getArguments().get(IApplicationContext.APPLICATION_ARGS)));
}
But how do I get the BundleContext, so that I can register services? It does not seem to be in the IApplicationContext.
Just came across this doing a web search, and thought I'd promote the new standard OSGi R4.2 way (as provided by Equinox shipped with Eclipse 3.5). If you don't have an activator, and don't want to create one just to cache the bundle context, you can use FrameworkUtil.getBundle. Modifying the previous example:
import org.osgi.framework.FrameworkUtil;
public class ExportClassDigestApplication implements IApplication {
public Object start(IApplicationContext context) throws Exception {
context.applicationRunning();
BundleContext bundleContext = FrameworkUtil.getBundle(this.getClass())
.getBundleContext();
}
}
Tricky internal way:
InternalPlatform.getDefault().getBundleContext()
could do it.
You will find an example in this class
public class ExportClassDigestApplication implements IApplication {
public Object start(IApplicationContext context) throws Exception {
context.applicationRunning();
List<ExtensionBean> extensionBeans = ImpCoreUtil.loadExtensionBeans("com.xab.core.containerlaunchers");
for (ExtensionBean bean : extensionBeans) {
ILauncher launcher = (ILauncher) bean.getInstance();
launcher.start();
}
ClassFilter classFilter = new ClassFilter() {
public boolean isClassAccepted(Class clz) {
return true;
}
};
PrintWriter writer = new PrintWriter( new File( "C:/classes.csv"));
Bundle[] bundles = InternalPlatform.getDefault().getBundleContext().getBundles();
Proper way:
Every plug-in has access to its own bundle context.
Just make sure your plug-in class overrides the start(BundleContext) method. You can then save it to a place classes in your plug-in can easily access
Note the bundle context provided to a plug-in is specific to it and should never be shared with other plug-ins.

Categories