I want to configure a self-written JCA 1.6 inbound resource adapter (RA). My big problem is that the RA needs to get access to some (dynamic) configuration data living in the application that uses the RA.
Now I know that this is against the original idea of the whole JCA idea but unfortunately I cannot change this design as quickly as I'd like/have to.
The data I need to get to the RA is
the port it's supposed to listen on,
the license used for the whole application (the feature the RA supplies requires extra licensing)
additional configuration data stored in a db
I've come up with four ideas:
Use the asadmin create-resource-adapter-config. Due to the fact that glassfish doesn't seem to restart apps depending on the RA, we need to restart the application after this. While this attempt is suitable for the port, it won't fit for the other data.
Use administered objects to give my application a means to pass data in to the RA. This idea is mentioned here. I guess this does it, but the spec states in chapter 13.4.2.3 that
Note, administered objects are not used for setting up asynchronous message
deliveries to message endpoints. The ActivationSpec JavaBean is used to hold all
the necessary activation information needed for asynchronous message delivery
setup.
But I cannot get any dynamic data to the ActivationSpec object (neither through a DeploymentDescriptor nor through annotations). Or did I miss something here? :-)
Use JDBC directly to access the data (also grabbed the idea from here). While this is presumably the best idea, it does not work for the mentioned licensing data as it is not stored in the db.
The last idea I had was to put a method in the MessageDrivenBean (through my interface) that is used to fetch data from within the RA. That method could be called from the RA and would supply the data. But: I just think that is quite abusive as it couples the RA to the app.
Dear community, what are your thoughts on this one? I'm afraid it's not so easy to find answers to these questions, so I'd be quite happy about opinions!
Thanks and cheers,
Julius
In the ra.xml there is the possibility to define config-properties. In Websphere these then show up as editable fields in a table of custom properties for the selected resource adapter. I'm working on a similar problem, I also need to pass hostname / port info to an RA. Unfortunately I haven't figured out how to read the contents of these fields from within the RA however.
The solution I finally came up with is to use the #ConfigProperty annotation. This means I use option one of my question above.
So my ResourceAdapter class looks like this:
public class Hl7ResourceAdapter implements ResourceAdapter {
#ConfigProperty
private Integer port = null;
// Rest from ResourceAdapter interface omitted here...
// Use port here to open socket...
}
The #ConfigProperty fields can now be set through either
a resource-adapter-config
the ra.xml deployment descriptor
Now in order to reconfigure these settings I use glassfish's REST interface to change these settings programmatically (one could also use the asadmin create-resource-adapter-config command). I circumvent the problem, that glassfish does not restart the application that uses the resource adapter by simply restarting it myself through REST. (To be precise: I disable the application and then reenable it to get around another bug in glassfish)
A few additional notes:
We deploy the resource adapter's .rar file into the .ear of the application using it.
We have a separate application outside glassfish (standalone) that calls the REST interface to do such things as restart the resource adapter application etc. It is obvious that an application cannot restart itself properly.
Hope this helps. kutuzof, will this get you any further?
Related
I am unable to find a code snippet for creating a datasource in Liberty via a Java Client. I looked up the ConnectionManagerMbean, but its documentation says that the Mbean instance wont be available until it is first used.
Can someone point me in right direction. I am kinda new to both Liberty and JMX so please bear with me if this sounds kinda rookyish.
Thanks in advance.
The reason you are unable to locate any examples of creating a Liberty data source via JMX is because it is not possible in Liberty to create data sources via JMX. In Liberty, data sources can be created via server configuration - the dataSource element - or via the #DataSourceDefinition annotation within an application component or <data-source> element within a deployment descriptor (such as web.xml) of an application.
Once you have created the data source, as you mentioned from the ConnectionManagerMBean documentation, you will need to use the data source first (access it from an application) before the MBean is made available. This aligns with Liberty's goals of having fast startup time and only loading/initializing what applications actually use. The behavior you observe sounds consistent with this, and you just need to perform an operation within your application first, and then you should hopefully be able to access the MBean.
I have a Dropwizard(v 0.7.1) based Jersey REST service. Currently I use one application connector port (8810) and I have two resources (say "/path1","/path2").
I will be able to access these resources as http:\\localhost:8810\path1 and http:\\localhost:8810\path2 respectively. What am trying to achieve is have a separate port for each resource. (e.g http:\\localhost:8810\path1 and http:\\localhost:8820\path2). I tweaked the yaml file to have the below configuration and when I started the application both resources were available using both ports and am not sure how to configure these resources to use specific ports or is that even possible with Dropwizard?
server:
applicationConnectors:
-
type: http
port: 8810
-
type: http
port: 8820
Appreciate if someone can enlighten.
Thanks
your issue is that the DefaultServerFactory adds all applicationConntectors to the same Handler, see DefaultServerFactory#build:
#Override
public Server build(Environment environment) {
printBanner(environment.getName());
final ThreadPool threadPool = createThreadPool(environment.metrics());
final Server server = buildServer(environment.lifecycle(), threadPool);
LOGGER.info("Registering jersey handler with root path prefix: {}", applicationContextPath);
environment.getApplicationContext().setContextPath(applicationContextPath);
final Handler applicationHandler = createAppServlet(server,
environment.jersey(),
environment.getObjectMapper(),
environment.getValidator(),
environment.getApplicationContext(),
environment.getJerseyServletContainer(),
environment.metrics());
LOGGER.info("Registering admin handler with root path prefix: {}", adminContextPath);
environment.getAdminContext().setContextPath(adminContextPath);
final Handler adminHandler = createAdminServlet(server,
environment.getAdminContext(),
environment.metrics(),
environment.healthChecks());
final RoutingHandler routingHandler = buildRoutingHandler(environment.metrics(),
server,
applicationHandler,
adminHandler);
server.setHandler(addStatsHandler(addRequestLog(server, routingHandler, environment.getName())));
return server;
}
What you need to do is implement your own ServerFactory.
You can extend DefaultServerFactory and overwrite the build method to set up your connectors in the way you want them to be.
Presumably you'll want to add some more configuration that indicates what goes where, since in terms of your yaml it will not be possible to map a resource to a specific connector. How would dropwizard know about that.
For overwriting the behaviour for dropwizard (adding a new ServerFactory) you can see this post I wrote about adding logging: Dropwizard doesn't log custom loggers to file
It basically involves implementing the class and making it discoverable for dropwizard. After that all you need to do is to change the yaml file to point to the correct ServerFactory.
If you don't like that approach, you can overwrite the get/set method on the configuration to return your class. For this, your class MUST extend DefaultServerFactory, since otherwise the yaml mapping won't work anymore. You can overwrite the build method regardless though.
Update:
Looking at it in a bit more detail, you'll run into a second problem:
Your Environment only has one jersey environment that it can use.
You will need to configure a second jersey environment since currently by default each Handler will get the same Jersey config passed to it (the only one that exists). This is why it will be available for all of your http configurations. So in summary:
Create a new Environment that supports multiple jersey configurations
Create a server factory that knows what jersey config belongs to which Handler and instantiates the handlers in that form.
I believe those two steps would be required.
In terms of environment, you will have to create your own ServerCommand (that is the command that starts up dropwizard server).
Looking in EnvironmentCommand#run you can see where the Environment is created. This will be the only place you can overwrite the default Environment (as far as I know) which is what you need to do to support multiple jersey configs.
To be honest with you, looking at this, I do not believe that this is what the dropwizard guys had in mind.
I have a Spring app running in WebLogic. In my DAO, it inherits a base class with a method that returns a "javax.sql.DataSource". I inject that datasource indirectly using the "jee:jndi-lookup" in my Spring application context to get the datasource from JNDI. When I look at this in the debugger, it appears to be a "weblogic.jdbc.common.internal.RmiDataSource".
I'd like to figure out how I can introspect into that datasource in my code to determine information about the database I'm connected to, particularly the host, port, SID, and username. Is there any way I could do that?
For some background, I have extensive diagnostics in my app for troubleshooting db connection and query issues. It would be very helpful if at runtime, I could introspect information about the WebLogic datasource from the database connection in use.
As I described, I already determined in the debugger what the actual type was, and I've examined all the obvious properties in that object for casting or reflection opportunities, and I don't see any obvious indications of information like "host", "port", or "SID".
I think you can use reflection and call all the getter methods of this class.
That should get you some helpful information. But based on the name of this class,
it looks like it's an internal WebLogic class and it's not really designed for this.
Still, you can do it with reflection, you can even call private getter methods with reflection.
Java Reflection API
The "right" JEE approach is not caring about these low-level details in code. After finding out which DataSource doesn't work, troubleshooting problems involves only application server logs and application server configuration tweaks.
There are several good reasons for insulating applications from DataSource details:
you aren't supposed to lose track of what abstract data sources you are using; using more than one DataSource (in fact, more than one Connection) in the same class is extremely unusual.
permanent data source configurations have been defined by you in your application server configuration, they are not secret or hidden.
transient data source state, on the other hand, is accessible through application server tools and logs.
on the third hand, data source implementations are proprietary and need to be freely optimized; expecting them to provide useful information is unreasonable.
your application is unlikely to be able to fix a troublesome data source; if it could, it would be able to mess with other applications in the same application server.
"replacing" a data source with another doesn't make any sense.
any scenario in which you want the definition of data source to vary according to circumstances should be dealt with by other means, mostly close to the DBMS (for example, if DBMS processes or machines are subject to shutdowns and restarts you could configure the servers as a cluster sharing the same IP address; relatively easy with Oracle).
I'm reading up on JMX for the first time, and trying to see if its a feasible solution to a problem we're having on production.
We have an architecture that is constantly hitting a remote web service (managed by a different team on their own servers) and requesting data from it (we also cache from this service, but its a sticky problem where caching isn't extremely effective).
We'd like the ability to dynamically turn logging on/off at one specific point in the code, right before we hit the web service, where we can see the exact URLs/queries we're sending to the service. If we just blindly set a logging level and logged all web service requests, we'd have astronomically-large log files.
JMX seems to be the solution, where we control the logging in this section with a managed bean, and then can set that bean's state (setLoggingEnabled(boolean), etc.) remotely via some manager (probably just basic HTML adaptor).
My questions are all deployment-related:
If I write the MBean interface and impl, as well as the agent (which register MBeans and the HTML adaptor with the platform MBean server), do I compile, package & deploy those inside my main web application (WAR), or do they have to compile to their own, say, JAR and sit on the JVM beside my application?
We have a Dev, QA, Demo and Prod envrionment; is it possible to have 1 single HTML adaptor pointing to an MBean server which has different MBeans registered to it, 1 for each environment? It would be nice to have one URL to go to where you can manage beans in different environments
If the answer to my first question above is that the MBean interface, impl and agent all deploy inside your application, then is it possible to have your JMX-enabled application deployed on one server (say, Demo), but to monitor it from another server?
Thanks in advance!
How you package the MBeans is in great part a matter of portability. Will these specific services have any realistic usefulness outside the scope of this webapp ? If not, I would simply declare your webapp "JMX Manageable" and build it in. Otherwise, componentize the MBeans, put them in a jar, put the jar in the WEB-INF/lib and initialize them using a startup servlet configured in your web.xml.
For the single HTML adaptor, yes it is possible. Think of it as having Dev, QA, Demo and Prod MBeanServers, and then one Master MBeanServer. Your HTML Adaptor should render the master. Then you can use the OpenDMK cascading service to register cascades of Dev, QA, Demo and Prod in the Master. Now you will see all 5 MBeanServer's beans in the HTML adaptor display.
Does that answer your third question ?
JMX is a technology used for remote management of your application and for a situation for example when you want to change a configuration without a restart is the most proper use.
But in your case, I don't see why you would need JMX. For example if you use Log4j for your logging you could configure a file watchdog and just change logging to the lowest possible level. I.e. to debug. This does not require a restart and IMHO that should have been your initial design in the first place i.e. work arround loggers and levels. Right now, it is not clear what you mean and what happens with setLoggingEnable.
In any case, the managed bean is supposed to be deployed with your application and if you are using Spring you are in luck since it offers a really nice integration with JMX and you could deploy your spring beans as managed beans.
Finally when you connect to your process you will see the managed beans running for that JVM. So I am not sure what exactly you mean with point 2.
Anyway I hope this helps a little
It's simple: I have an MDB and an EJB that sends messages to a topic (or queue). JBoss complains that the topic is not bound to the JNDI context.
I want to have the topic/queue to be automatically created at best, or at least to have a standard way to define it, per application (say, in ejb-jar/META-INF)
this question and this blogpost show us how to do it in an application server specific way. This surely works, but:
I want to use the #MessageDriven annotation
I want the setting not to be global for the application server
I want the setting to be portable
It seems impossible to do this, with JavaEE 5 at least.