In a CXF SOAP webservice, I'm using the following annotations to disable the xsd validation:
#EndpointProperties({
#EndpointProperty(key = "set-jaxb-validation-event-handler", value = "false")
})
I would like the validation to controlled at runtime (enable/disable it, based on the value of a setting retrieved from a database). My question is: is it possible to disable/enable this handler at runtime? Maybe by writing a custom event handler and not using this property at all?
Thanks.
Edit: an option would be not to disable the validation with set-jaxb-validation-handler, and rather subclass ValidationEventHandler. As explained here, I would then check the database setting in handleEvent and return according to its value.
But there are still a few downsides with this approach: first, this webservice is configured with annotations, and I can't seem to find a way to apply a ValidationEventHandler with annotations (same question as: How to set custom ValidationEventHandler on JAXB unmarshaller when using annotations).
Secondly, it means that the validation will be performed even if I don't need it; I would then lose any performance benefit.
It doesn't in fact exactly suit my needs, so I'm still open to any suggestion.
Yes, it is possible.
MyService service = new MyService();
MyServiceInterface port = service.getMyServicePort();
BindingProvider bindingProvider = (BindingProvider) port;
bindingProvider.getRequestContext().put(
"set-jaxb-validation-event-handler", Boolean.FALSE);
I finally found a working solution.
As I'm running CXF on JBoss EAP 6.0, I added the following configuration to the webservices subsytem in standalone.xml:
<subsystem xmlns="urn:jboss:domain:webservices:1.2">
<!-- ... -->
<endpoint-config name="myconfig">
<property name="set-jaxb-validation-event-handler" value="false"/>
</endpoint-config>
<!-- ...-->
</subsystem>
And the following annotation to the SEI implementation:
#org.jboss.ws.api.annotation.EndpointConfig(configName = "myconfig")
This is the related Maven dependency:
<dependency>
<groupId>org.jboss.ws</groupId>
<artifactId>jbossws-api</artifactId>
<version>1.0.1.Final</version>
<scope>provided</scope>
</dependency>
We still need a restart of the server if we want to change the property value, but it's a lesser evil.
For the people trying to configure that on the bus level, the following worked for me:
<cxf:bus id="soapClientCxfBus" bus="soapClientCxfBus" >
<cxf:properties>
<entry key="set-jaxb-validation-event-handler" value="false" />
</cxf:properties>
</cxf:bus>
Related
I had cxf.xml file:
<beans ....
<cxf:bus>
<cxf:features>
<cxf:logging/>
</cxf:features>
</cxf:bus>
</beans>
but during some operations, i got error:
org.apache.cxf.interceptor.Fault: Unmarshalling Error: Maximum Number of Child Elements limit (50000) Exceeded
and I found out that it can be overridden with org.apache.cxf.stax.maxChildElements value. So i first tried putting org.apache.cxf.stax.maxChildElements=120000 in gradle, in IDEA arguments, which didnt work, so i modified my .xml file like this:
<cxf:bus>
<cxf:features>
<cxf:logging/>
</cxf:features>
<cxf:properties>
<entry key="org.apache.cxf.stax.maxChildElements" value="120000"/>
</cxf:properties>
</cxf:bus>
but none of this worked, and I am currently without ideas, as of why this setting is not getting registered.
Im working with libraries cxf-rt-frontend-jaxws and cxf-rt-transports-http both on version 3.2.7.
You can try doing configuration via java code as well.
You can get Bus instance which is used for creating your org.apache.cxf.endpoint.Client:
YourActual service = //return instance of your #WebService class by defining address & interpreter;
Client client=ClientProxy.getClient(service);
client.getBus().setProperty(StaxUtils.MAX_CHILD_ELEMENTS,120000)
Or if you have your endpoint implementor then you can do :
Bus bus=BusFactory.getDefaultBus();
bus.setProperty(StaxUtils.MAX_CHILD_ELEMENTS,120000);
Object implementor = <Your service implementation class>;
EndpointImpl ep = (EndpointImpl) Endpoint.publish(yourendpoint, implementor);
ep.setBus(bus);
Above Bus configuration psudo-code taken from CXF doc.
If when you say "IDEA Arguments" you mean this box (labeled: Program Arguments)...
Try instead enabling Modify Options -> Add VM Options
Then write your VM Option string in the box labeled VM options.
try
-Dorg.apache.cxf.stax.maxChildElements=1000000
This may or may not work depending on what you meant by IDEA Arguments. I have had IDEA ignore many options that I have tried to pass to the JVM via the "Program Arguments" box at work. Hopefully this resolves your issue. If this fails, I will try to monitor this thread.
I have the following scenario:
There will be a Java language testbed system consisting of a number of "services" that collaborate by passing messages to one another. The service implementation is intended to be generic, i.e. there is no specific "business logic" contained within. For the purposes of the testbed it is important to be able to create various collections of services, configured externally (if possible).
The services themselves are unaware of the existence of any other service. Each service simply subscribes to the topics where it expects to receive information and publishes on topics where it sends information out to any waiting subscribers. With careful configuration it then would be possible to simulate a data flow graph.
The plan is to configure a given service instance by providing configuration information that describes the information needed to set up subscribers (readers) and publishers (writers). The configuration information may include other properties not related to publish/subscribe.
Below is a possible example:
Note: XML was chosen for the example simply because it's easy enough to read and allows for structured data.
<service>
<name>Service A</name>
<service-id>service ID</service-id>
<publish>
<per-second>5</per-second>
<topic>
<name>Topic 1</name>
<class>org.xyz.Topic1</class>
<!-- override 5/sec rate -->
<per-second>10</per-second>
</topic>
<topic>
<name>Topic 2</name>
<class>org.xyz.Topic2</class>
</topic>
</publish>
<subscribe>
<topic>
<name>Topic 3</name>
<class>org.xyz.Topic3</class>
</topic>
</subscribe>
</service>
<service>
<name>Service B</name>
<service-id>service ID</service-id>
<publish>
<per-second>30</per-second>
<topic>
<name>Topic 3</name>
<class>org.xyz.Topic3</class>
</topic>
</publish>
<subscribe>
<topic>
<name>Topic 2</name>
<class>org.xyz.Topic2</class>
</topic>
</subscribe>
</service>
...
I would like to use the Spring framework to help with the configuration of these services. Note: I am very new to Spring and am currently reading Spring in Action (and other sources) to educate myself.
What I would like to know is: How could I "inject" the configuration information to some sort of controller or factory that would then use it to create the collection of services and provide them with the necessary information to create the readers and writers they will use to receive and send messages?
From what I've read so far, Spring appears to be pretty powerful WRT to dependency injection and "bean wiring", but I don't know enough about what can (and cannot) be done, nor how to do it.
I'm not partial to whether Spring is configured by Java or XML. I just used XML because it easy to put together, allows for data structuring and seems to be used everywhere. If it makes more sense to specify the configuration a different way, just let me know.
How a given service would handle an event (i.e. receive a specific message) to possibly send out a message "response", or take some other action, is a topic outside the scope of this question. I am researching how that could be done - mainly at rules based processing. If anyone has suggestions, I will gladly take a look at them.
Make a config file like this:
some.paremeter=cool
some.other.parameter=awesome
named myconfig.properties. Make sure the file is in your classpath, then include -Dspring.config.name=myconfig in your vm args; then in the xml you can use ${some.parameter} etc. In particular, putting the config file in <project-root>/config/ will work.
For example, here is a simple MongoClient from one of my projects that uses a spring config:
<!--Mongo-->
<bean id="mongoClient" class="com.mongodb.MongoClient">
<constructor-arg>
<bean class="com.mongodb.MongoClientURI">
<constructor-arg type="java.lang.String"
value="mongodb://${mongo.db.user}:${mongo.db.password}#${mongo.db.host}:${mongo.db.port}/${mongo.db.database}"/>
</bean>
</constructor-arg>
</bean>
I extended AbstractByteArraySerializerand now I want to use this serializer like the rest of the available TCP serializers (LF, NULL, L1, ...).
I found the profiles in tcp-encdec.xml and registered my own profile:
...
<beans profile="use-custom">
<bean id="CUSTOM"
class="custom.tcp.serializer.ByteArrayCustomSerializer">
<property name="maxMessageSize" value="${bufferSize}" />
</bean>
</beans>
...
Spring uses EncoderDecoderMixins.Encoding to convert Encoding to a specific profile.
EncoderDecoderMixins.Encoding is an enum in a final class. Spring converts the decoder TCP property to a specific profile based on this enum. My CUSTOM serializer won't work since it isn't in the specified Encodings.
Is there a way to register a new Encoding or do I have to write a new Source module to use my serializer?
Unfortunately, you will need a custom source; we could probably add another enumeration, such as CUSTOM, where you provide the classname of the deserializer but that will need a change to the standard source.
A quick and dirty work-around would be to modify the source locally:
<int-ip:tcp-connection-factory id="connectionFactory"
...
deserializer="myDeserializer"/>
<bean id="myDeserializer" class="foo.Deser" />
i.e. change the ${decoder} placeholder to point to your bean.
Consider the following mule configuration and having mule embedded in a Web (Java EE) Application:
<jms:connector
name="jmsConnector"
connectionFactory-ref="jmsConnectionFactory"> <!-- From spring -->
<!-- JNDI Name Resover here? -->
</jms:connector>
<flow name="mainTestFlow">
<jms:inbound-endpoint connector-ref="jmsConnector"
queue="jms/MessageQueue" />
<logger level="INFO" category="mule.message.logging" message="Message arrived." />
</flow>
jmsConnectionFactory refers to a JMS Connection Factory defined in Spring, from:
<bean id="jmsConnectionFactory" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="jms/QueueConnectionFactory" />
</bean>
The Queue Connection Factory was tested and is working.
The jms/MessageQueue queue name refers to a resource-ref defined in the web application web.xml file. This JNDI reference is bound at the container level to a javax.jms.Queue managed by the application server and connected to a proper messaging server (ActiveMQ, in this case).
However, Mule doesn't treat the queue="" attribute as a JNDI destination, but as the queue name itself. So, when the above code is initialized, it actually creates a new queue in ActiveMQ named "jms/MessageQueue". What I really wanted was that it correctly retrieved the queue from the JNDI reference in the Web Application descriptor.
Ok, you could say, all I had to do was to configure a JNDI Name Resolver at the JMS Connector and also add the jndiDestinations="true" and forceJndiDestinations="true" attributes to it.
This is acceptable:
<jms:default-jndi-name-resolver
jndiProviderUrl="tcp://localhost:1099"
jndiInitialFactory="???"/>
The real problem is that I don't want to place the real Initial Context Factory class name in the jndiInitialFactory, because it would fall into a container-specific definition. However, my application is sometimes deployed into JBoss 4.2.3, and sometimes, into WebSphere 7. Having 2 configurations and 2 EAR packages is not an option, due to our development process.
Anyway, is it anyhow possible to either tell Mule-ESB to assume the current container (as it is in embedded mode) as the default JNDI Initial Factory for lookups or provide a "generic" JNDI Initial Factory that would recognize the container's JNDI environment? That shouldn't be a problem, because a web application can refer to it's container JNDI environment without additional (or even visible) configuration.
If not possible, can I have my jms:inbound-endpoint refer to a javax.jms.Queue defined in Spring, just as the jms:connector does with the JMS Connection Factory? That would actually be rather elegant and clean, as Mule is Spring-friendly.
Thank you all in advance!
Solution
After much thought and consideration, I finally solved my problem by creating a custom JndiNameResolver wired up to spring JNDI facilities (JndiTemplate, for instance). This is far from the best solution, but I found that to be the one that would least interfere and tamper with Mule's and Spring's inner intricacies.
That said, here is the class:
package com.filcobra.mule;
import javax.naming.NamingException;
import org.mule.transport.jms.jndi.AbstractJndiNameResolver;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.jndi.JndiObjectLocator;
import org.springframework.jndi.JndiTemplate;
public class SpringJndiNameResolver extends AbstractJndiNameResolver implements InitializingBean {
private static Logger logger = LoggerFactory.getLogger(SpringJndiNameResolver.class);
private JndiTemplate jndiTemplate;
#Override
public void afterPropertiesSet() throws Exception {
if (jndiTemplate == null) {
jndiTemplate = new JndiTemplate();
}
}
#Override
public Object lookup(String name) throws NamingException {
Object object = null;
if (name != null) {
logger.debug("Looking up name "+name);
object = jndiTemplate.lookup(name);
logger.debug("Object "+object+" found for name "+name);
}
return object;
}
public JndiTemplate getJndiTemplate() {
return jndiTemplate;
}
public void setJndiTemplate(JndiTemplate jndiTemplate) {
this.jndiTemplate = jndiTemplate;
}
}
With that, the configuration falls back into the usual:
<spring:bean id="jndiTemplate" class="org.springframework.jndi.JndiTemplate" />
<jms:connector
name="jmsConnector"
connectionFactoryJndiName="java:comp/env/jms/MyConnectionFactory" <!-- from Resource-Ref -->
jndiDestinations="true"
forceJndiDestinations="true"
specification="1.1" >
<jms:custom-jndi-name-resolver class="com.filcobra.mule.SpringJndiNameResolver">
<spring:property name="jndiTemplate" ref="jndiTemplate"/>
</jms:custom-jndi-name-resolver>
</jms:connector>
With that, I was finally able to not have my Mule ESB installation tied up to a specific JMS vendor/implementation. In fact, the JMS (queues and factories) configuration is all left under the application server responsibility.
Nevertheless, one thing remained odd. I expected that the JMS endpoints also used my Jndi Name Resolver in order to lookup the queue from a resource-reference, or its JNDI Name, the same way it did with the Connection Factory. That wouldn't work whatsoever. I finally worked around that by placing the queue name itself, as created in the JMS server:
<flow name="mainTestFlow">
<jms:inbound-endpoint connector-ref="jmsConnector" queue="queue/myQueue"/> <!-- Queue Name, not JNDI Name -->
That worked. So, I'm assuming the JMS Connector doesn't try and look up the queue, but simply uses the connection factory (looked up or not) to directly access the JMS Server.
Regards!
I see the problem in the source code: basically if you provide an externally created connection factory, jndiDestinations and forceJndiDestinations are forcefully set to false.
I haven't messed with JNDI enough recently to provide a generic solution to your problem, which indeed would be the best.
What I would try would be to sub-class org.mule.transport.jms.Jms11Support, inject my Spring looked-up queues in it, rewire it internally to use these queues and, lastly, inject it in the Mule JMS connector itself.
Spring Annotations - I am getting some documents regarding Annotations but, they are explaining each annotation and how to use it.
but i want, know how can achieve same annotations behavior with bean configuration.
ex:
Annotation Bean config
#Required ?
Can you help.................
I don't really understand your question, but here are some links from the Spring Reference that seem relevant:
3.9. Annotation-based container configuration
3.11. Java-based container configuration
On second thought (and after editing your question's source) I seem to understand. I think you want an XML alternative to the #Required annotation.
Quote from the #Required section:
The container throws an exception if the affected bean property has not been populated; this allows for eager and explicit failure, avoiding NullPointerExceptions or the like later on.
I'm not sure such a thing exists in XML, I think the only way to get that behavior is through explicit wiring.
<bean class"foo.bar.Service.class">
<!-- This will fail if no bean named subService is available -->
<property name="subService" ref="subService" />
</bean>