Custom exception mapping for bean validation on TomEE 7? - java

Context
We use a javax.ws.rs.ext.ExceptionMapper<Exception> annotated as #javax.ws.rs.ext.Provider to handle all exceptions. Internally this ExceptionMapper is distinguishing between different types of exceptions to determine what information to reveal to the client.
In the case of the javax.validation.ConstraintViolationException, we return additional information about which field was invalid and why.
Problem
We just switched from TomEE 1.7.2 JAX-RS to TomEE 7.0.0-SNAPSHOT webprofile.
With TomEE 1.7.2 JAX-RS we used the openejb.jaxrs.providers.auto=true system property, our ExceptionMapper was automatically found and used.
With TomEE 7.0.0-SNAPSHOT webprofile the property is no longer necessary to benefit from auto discovery.
However the org.apache.cxf.jaxrs.validation.ValidationExceptionMapper is also discovered and now acts as the preferred ExceptionMapper for the javax.validation.ConstraintViolationException. Our own ExceptionMapper does not run, and the client therefore gets no information about what went wrong during validation.
Our own ExceptionMapper<Exception> still handles all other exceptions.
What I already tried
"duplicate" the specialized ExceptionMapper
I placed my own javax.ws.rs.ext.ExceptionMapper<javax.validation.ConstraintViolationException> next to my resources, hoping that it takes precedence over the CXF one.
Still the org.apache.cxf.jaxrs.validation.ValidationExceptionMapper takes precedence.
Update: it turned out that this indeed does the trick. I don't know why my initial test didn't work.
Disable the ValidationExceptionMapper via system.properties
In the changelog of TomEE 7.0.0-SNAPSHOT I noticed
TOMEE-1336 Support classname.activated = true/false for auto discovered providers
Looking at the corresponding changeset I was hopeful that I could just disable the org.apache.cxf.jaxrs.validation.ValidationExceptionMapper by adding
org.apache.cxf.jaxrs.validation.ValidationExceptionMapper.activated=false
to our system.properties.
This remained without effect.
Questions
Is this CXF or TomEE behaviour?
How do we configure which ExceptionMapper takes precedence?

Makes some time now but think it is needed by spec but you can disable it by setting cxf.jaxrs.skip-provider-scanning=true.
It completely disables auto providers including the scanned ones but then you can control the one you want in openejb-jar.xml - surely the best and safer solution IMHO cause otherwise you depend a lot of the libs and container setup you use.
There is no priority afaik cause the exception hierarchy is used.
edit: missed a part: you need to impl ExceptionMapper{ValidationException} otherwise CXF one has higher priority than your own one (Exception is less specific)
edit 2: https://issues.apache.org/jira/browse/TOMEE-1656 for the activated support

Related

How to properly handle exceptions in ManagedServiceFactories?

The OSGi ConfigurationAdmin specification mentions that implementations of ManagedService and ManagedServiceFactory may signal an invalid incoming configuration by throwing a ConfigurationException. Yet, apart from this statement, the spec is silent on how the various actors should handle the situation, and most importantly, what should be the state of the environment after such an exception.
For example, suppose that a ManagedServiceFactory currently has a service instance (lets say service.pid=example.12345) with a valid set of properties; that service instance is published by the factory into the service registry. Then, the factory is informed of a configuration update for that service instance; however, on verification, the update method determine that incoming properties are invalid. Based on the spec, the factory should therefore throw a ConfigurationException.
But then, if nothing else is done, the environment remains in an unstable state: there is now a published service in the registry based on a configuration that no longer exists; consequently, whenever the ManagedServiceFactory service gets restarted (for example because of a bundle update or a whole framework restart), it will not be possible to reinstantiate that service, its former valid configuration having been lost. This breaks the persistence paradigm of the Configuration Admin subsystem, and pose severe issues regarding the stability of some OSGi environment.
Unfortunately, there is no easy way for the initial configurator bundle to detect that its configuration change caused a ConfigurationException, making it hardly possible in general to restore a stable configuration from that place. It seems to me that it would be more appropriate, in such situation, for the ConfigurationAdmin to (persistently) restore the previously valid configuration, but there is unfortunately no mention of such behaviour in the spec, and I don't see any trace of such mechanism in Felix's implementation.
Given these facts, it seems that the only possibility to maintain the stability of the environment would be for a ManagedServiceFactory implementation to first unregister and destroy existing service instances for which it has received invalid configuration properties, and only after that, throw the mandated ConfigurationException. This would effectively result in the same environment state as what would be if the framework was relaunched at that point. Similarly, a ManagedService implementation should handle an invalid configuration by first entirely restoring its default configuration, and then throw a ConfigurationException.
So, how exactly should errors in ManagedService and ManagedServiceFactories configuration updates be handled? Is my understanding correct? From what I see out there in example/open source implementations of ManagedService and ManagedServiceFactory, this aspect seems to be totally ignored by most developers. Does the spec provides any clarification on the subject?
The general strategy is to log it as an error and pray it will be solved soon. The purpose of the Configuration Exception is to provide detailed information to the devops so it can be corrected quickly.
The strategies you describe are imho so hopelessly complex and open ended that they tend to create more problems then they ever can solve. Someone made a mistake to create wrong configuration, the only solution is to fix that configuration. I find that in general systems that handle these exceptional case to become very fragile. Once something is wrong, you're in an infinite space and software is extremely bad in reasoning about things you don't know about.
So unless you have some very specific use cases I do not think it can, nor should it, have a general solution.
In general there are three strategies to handle this:
Rejecting the invalid configuration but keeping the previous state
Rejecting the invalid configuration and destroy the current state as if there was no configuration before
Rejecting invalid values, apply valid values as much as possible
What to choose, an wheather you descide to throw an exception, print a warning to the log, send an e-mail or bring up a popup heavyly depends on your system and use cases.
For example if you have an UI and the user can change the config you can simply save the old config and if you detect an error you can ask the user to either correct or revert the configuration.
Even better, you can describe the Configuration requirements with the MetaTypeService so you can validate the config before apply it.
If you have a set of config files, you better make a backup before so you can revert :)

CXF 3.1.5 vs. 2.7.17 - Access SOAP via HTTP GET

I've got a SOAP JAXWS WebService here that was running fine with CXF 2.7. It also included the feature that I simply could access it via an URL, for example...
http://localhost:8080/webservices/myService/someMethod?someParameter=1&someOtherParameter=2
...which would result in an XML response. Unfortunately, I had to switch to CXF 3.1.5 (because of compatibility problems with more recent Spring versions) and now this feature seems to be gone, the only answer I get now is...
No binding operation info while invoking unknown method with params
unknown
Has anyone an idea where I can re-enable this feature (while I personally don't need it, some other people accessing the service with their own tools may depend on it)? Perhaps I was missing some dependency when moving to 3.1.5...
Looks like the problem is the URIMappingInterceptor that has been removed from the default chain (and the code, since it was deprecated, see the migration guide) for security reasons. Unfortunate for people who depend on the HTTP Get mapping it did... Of course I could re-introduce it, but there's still the hope that there is a better, security-aware way of doing it...

JAXWS Client Timeout on Jboss

how can i set timeout for JAXWS client, Im using Jboss 5.1.
I was trying to do this with
bp.getRequestContext().put("com.sun.xml.ws.connect.timeout", 100);
bp.getRequestContext().put("com.sun.xml.ws.request.timeout", 100);
but it doesn't works. It works fine for standalone client.
When i tried to use
bp.getRequestContext().put("com.sun.xml.ws.request.timeout", 100);
I.ve got org.jboss.ws.core.WSTimeoutException: Timeout after: 100ms, but it is heppening after 300 (3*100 ms).
Can anyone help me with this issue.
While this looks likely to be an oversight on your part, The settings for JAX-WS timeouts might depend on the specific RI you're building on.
You could try these settings (they are paired to be used in pairs)
BindingProviderProperties.REQUEST_TIMEOUT
BindingProviderProperties.CONNECT_TIMEOUT
BindingProviderProperties should be from com.sun.xml.internal.WS.client
Or the strings
javax.xml.ws.client.connectionTimeout
javax.xml.ws.client.receive timeout
All properties to be put on getRequestContext() in milliseconds.
BtW, how were you able to time the milliseconds without code :)?
JAXWS use the JAXB for marshalling and unmarshalling.
In the container probably it's taking more time because it's JAXContext scanning your classpath.
If that's the case try eager initialization of JaxBContext:
JBossWS may perform differently during the first method invocation of
each service and the following ones when huge wsdl contracts (with
hundreds of imported xml schemas) are referenced. This is due to a
bunch of operations performed internally during the first invocation
whose resulting data is then cached and reused during the following
ones. While this is usually not a problem, you might be interested in
having almost the same performance on each invocation. This can be
achieved setting the org.jboss.ws.eagerInitializeJAXBContextCache
system property to true, both on server side (in the JBoss start
script) and on client side (a convenient constant is available in
org.jboss.ws.Constants). The JAXBContext creation is usually
responsible for most of the time required by the stack during the
first invocation; this feature makes JBossWS try to eagerly create and
cache the JAXB contexts before the first invocation is handled.
http://www.mastertheboss.com/javaee/jboss-web-services/web-services-performance-tuning

Tell OpenEJB to ignore MDB

I wrote an unit-test for an activity which finally puts a message into a queue. As soon as a message is put into that queue, a message driven bean starts processing. But I don't want to test MDBs in a unit test. How can I tell OpenEJB to ignore them?
I set up OpenEJB with several properties:
p.setProperty(Context.INITIAL_CONTEXT_FACTORY,
"org.apache.openejb.client.LocalInitialContextFactory");
p.setProperty("openejb.deployments.classpath.include", ".*");
p.setProperty("openejb.localcopy", "false");
// Messaging
p.put("MyJmsResourceAdapter",
"new://Resource?type=ActiveMQResourceAdapter");
// Do not start the ActiveMQ broker
p.put("MyJmsResourceAdapter.BrokerXmlConfig", "");
p.put("MyJmsConnectionFactory",
"new://Resource?type=javax.jms.ConnectionFactory");
p.put("MyJmsConnectionFactory.ResourceAdapter", "MyJmsResourceAdapter");
p.put("queue/MyQueue",
"new://Resource?type=javax.jms.Queue");
I know I must set openejb.deployments.classpath.exclude, but I can't figure out the right value:
p.setProperty("openejb.deployments.classpath.exclude", "org.example.mdb.*");
For example my class is named org.example.mdb.MyMDB.
just my 2 cents:
try ".*org/example/mdb.*" or ".*org.example.mdb.*"
from Loading Deployments from the Classpath:
Note by default these settings will
only affect which jars OpenEJB will
scan for annotated components when no
descriptor is found. If you would like
to use these settings to also filter
out jars that do contain descriptors,
set the
openejb.deployments.classpath.filter.descriptors
property to true. The default is false
We don't have that feature, but it could easily be added if you wanted to do a little hacking -- new contributions and contributors are always welcome.
This class will do exactly what you want... and a few things you probably don't want :) It strips out all MDBs and JMS resource references (the good part) and it strips out all entity beans and persistence unit references (the part you probably don't want). We wrote it due to some debugging issues we were having when either ActiveMQ or OpenJPA were loaded. If you cleaned it up we'd happily take it back and support it as a feature.
There is a similar feature which strips out all web services. It is installed in the ConfigurationFactory if a specific system property is set. Should be easy to plug an "MDB & JMS" remover using a similar flag at basically that same place in ConfigurationFactory
In fact since in OpenEJB all annotation and xml meta-data is merged into one object tree (which is also a JAXB tree), you could do pretty powerful transformations of the app prior to it being actually deployed. Say for example swap out specific beans for mock versions.
One of those things I think would make an excellent feature but haven't yet had the time to work on. I.e. making some clean hook for people to mess with the tree just before we send it off for deployment. Anyone reading this is welcome to jump in and take a stab at it (yay open source!).

What are the best debugging tricks with Weld/CDI?

One of the beauties with Java EE 6 is the new dependency injection framework - CDI with the Weld reference implementation - which has prompted us to start migrating internally to JSR-330 in an implementation agnostic manner, with the explicit target of being able to have a core jar which is frozen, and then being able to add extra jars providing new modules replacing functionality in the core jar.
I am now in the process of making the above work with Weld, and to be frank there is simply too much magic going on behind the covers. Either it works or it doesn't, and it doesn't provide very much help by default on what happens so you can investigate what is wrong and fix it.
I would expect that there are switches to switch which can easily enable things like:
What classpath entries are scanned and where? What was the result?
What beans are available for injection for which class?
What caused a given bean not to be considered for later? A given jar?
In other words, I need to see the decision process in much more detail. For some reason this is not as needed with Guice, perhaps because there is much less magic, and perhaps because the error messages are very good.
What do you do to debug your Weld applications, and how much does it help?
Short answer: there is no dedicated debug option for CDI (as no such thing is required by the spec), and no dedicated debug option for Weld.
Long Answer: There is a lot you can do on your own. Familiarise yourself with the extension mechanism of CDI, and you'll discover that you can easily (really!) write your own extension that debugs your required information
What classpath entries are scanned and
where? What was the result?
Listen to the ProcessAnnotatedType-Event
What beans are available for injection
for which class?
Query the BeanManager for that.
What caused a given bean not to be
considered for later? A given jar?
Listen to the AfterBeanDiscovery-Event and see what you've got in the BeanManager. Basically, the following scenarios make a ManageBean ineligible for injection:
it's no ManagedBean (like there is no beans.xml in the jar)
it does not qualify as a managed bean (https://docs.jboss.org/weld/reference/1.1.0.Final/en-US/html/beanscdi.html#d0e794)
it has no BeanType (#Type{})
it is vetoed (Seam Solder) or suppressed by any other extension-mechanism
Weld uses Simple Logging for Java (sl4j). If you are using Tomcat, I suggest you add sl4j-jdk14-x.x.x.jar to application class path and append following lines to apache-tomcat-7.0.x/conf/logging.properties:
org.jboss.weld.Bootstrap.level = FINEST
org.jboss.weld.Version.level = FINEST
org.jboss.weld.Utilities.level = FINEST
org.jboss.weld.Bean.level = FINEST
org.jboss.weld.Servlet.level = FINEST
org.jboss.weld.Reflection.level = FINEST
org.jboss.weld.JSF.level = FINEST
org.jboss.weld.Event.level = FINEST
org.jboss.weld.Conversation.level = FINEST
org.jboss.weld.Context.level = FINEST
org.jboss.weld.El.level = FINEST
org.jboss.weld.ClassLoading.level = FINEST
This will generate lots of debug in console, so you`d better select something specific and comment out other lines.
Other logging libraries (like log4j) can be configured using their respective config files and adding similar levels.
I can suggest a few options:
lower the logging threshold. I don't know what logging framework is used by Weld, but you can see that and configure, say, DEBUG or INFO
get the source code and put breakpoints in the BeanManager implementation (BeanManagerImpl perhaps). It is the main class in CDI and handles almost everything.
Try putting a different implementation (if not tied by the application server) - for example OpenWebBeans. Its exception messages might be better
Open the specification and read about the particular case. It is often the case the you have missed a given precondition - for example an annotation has to have a specific #Target, otherwise it is not handled by CDI.
I can confirm that the exception messages of Weld are rather disappointing. I haven't used Guice, but in Spring they are very, very informative. With Weld I had to refer to the 4th point above (opened the spec) and verify all preconditions. This was my suspicion initially - that even though the spec looks very good, the implementations will not be as shiny (at first at least). But I guess one gets used to this.

Categories

Resources