CXF server-side logging to a table - java

In CXF, you can enable logging using this:
<cxf:bus>
<cxf:features>
<cxf:logging/>
</cxf:features>
</cxf:bus>
Source: http://cxf.apache.org/docs/configuration.html
Everything seems to go to files or console and can be configured using Log4j as well it seems.
My question is, how do you enable logging on server side so that you can intercept these raw requests and responses and store them in a table in the database along with other application specific information related to the service call.
This is all for server-side service implementation class.

The example you quoted was the simplest possible config to do basic logging. If you look at the example right before, you can see a slightly more expanded approach to logging interceptors:
<cxf:bus>
<cxf:inInterceptors>
<ref bean="logInbound"/>
</cxf:inInterceptors>
<cxf:outInterceptors>
<ref bean="logOutbound"/>
</cxf:outInterceptors>
<cxf:inFaultInterceptors>
<ref bean="logOutbound"/>
</cxf:inFaultInterceptors>
</cxf:bus>
Here, the logInbound, logOutbound and logOutbound beans are any implementation of CXF's interceptor interface. You can implement your own interceptor beans to do any type of logging you choose, including database logging.

Related

How to know when Spring/CXF is ready to take requests?

I have a java web application using Apache CXF and JAX/RS to implement an API. We are running our webapp under tomcat. I need to implement something in my application that calls out to an external service, which may call my application back again. I need to call that external service only after CXF finishes initializing and is ready to accept external API requests. I have checked out servlet context listeners, CXFServlet, application context refresh, and other things, but can't see anything that is called late enough in the process for CXF to begin accepting requests. Or do I need to trigger on some event from tomcat?
If you define the CXF dependency as bean in spring configuration it will be loaded and ready when application starts. As you are aware spring beans are loaded and resolved during application startup, you can additionally have pre initialization and post initialization functions e.g. #PostConstruct.
Example configuration from reference https://www.luckyryan.com/2013/06/15/apache-cxf-exception-handler-for-jaxrs-rest/ :
<!-- rest container -->
<jaxrs:server id="sampleSerivceREST" address="/rest">
<jaxrs:serviceBeans>
<ref bean="sampleServiceRESTGateway"/>
</jaxrs:serviceBeans>
<jaxrs:providers>
<bean class="org.codehaus.jackson.jaxrs.JacksonJsonProvider"/>
<bean class="com.luckyryan.sample.service.ExceptionHandler"/>
</jaxrs:providers>
</jaxrs:server>
<!-- soap container -->
<jaxws:endpoint
id="sampleServiceSOAP"
implementor="#sampleServiceSOAPGateway"
address="/soap"
serviceName="sampleSoapService"/>

Integration testing with ActiveDirectoryLdapAuthenticationProvider

Last time I've added to our project one more authentication provider in order to authenticate user through windows active directory server:
<security:authentication-manager id="authenticationManager" erase-credentials="true">
<security:authentication-provider ref="ldapActiveDirectoryAuthProvider" />
<security:authentication-provider ref="authenticationProvider1"/>
<security:authentication-provider ref="authenticationProvider2"/>
</security:authentication-manager>
<bean id="customLdapUserDetailsMapper" class="security.authentication.customLdapUserDetailsMapper">
</bean>
<bean id="ldapActiveDirectoryAuthProvider" class="org.springframework.security.ldap.authentication.ad.ActiveDirectoryLdapAuthenticationProvider">
<constructor-arg value="my.domain"/>
<constructor-arg value="ldap://my.custom.host:389" />
<property name="useAuthenticationRequestCredentials" value="true" />
<property name="convertSubErrorCodesToExceptions" value="true" />
<property name="userDetailsContextMapper" ref="customLdapUserDetailsMapper" />
</bean>
Alsmost work fine except existing integration tests that work with authentication flow. Namely each test tried to connect to server when ActiveDirectoryLdapAuthenticationProvider.bindAsUser then failed because my.custom.host is unavaible for this type of test.
I've started googling in order to find some mock for this type of test, but unfortunatly I found only this post Integration tests with spring-security and ldap where Luke Taylor recommended use existing integration tests as a guide. I've took a look into it but it doesn't contain any tests for this type of provider.
I'm new in such stuff and would be good to know the following things:
Will be it correct to reuse in any manner this approach with new ApacheDSContainer("dc=springframework,dc=org", "classpath:test-server.ldif"); that was mentioned in LDAP integration test(I am not sure wheter it suites to me because I didn't create ldap ebbedded ldap server in my application context and didn't specify any .ldif files in mentioned configuration as well).
In which way the following provider can be mocked in proper way?
Actually you just have to provide another configuration which will be loaded for Testing purposes. There you can define a different Authentication Provider, which for example just can authenticate everyone.... Or just simply deactivate Authentication at all.
Since you don't want to test the functionallity provided by spring.

How to prevent cxf logging?

I want to disable logging of org.apache.cxf.interceptor.Fault.
So I found I have to create a folder /META-INF/cxf with file org.apache.cxf.Logger.
BUT what do I have to put in there to set cxf logging level to NONE?
you may need to comment below code in your cxf configuration xml file.
<cxf:bus>
<cxf:features>
<cxf:logging/>
</cxf:features>
</cxf:bus>

passwordCallback in CXF

I develop a webservice client for an existing webservice. I am using Apache CXF 2.2. The service requires security with Username and plain text password, which I configured like this:
<bean id="myPasswordCallback"
class="com.kraemer_imd.mobilized.m2m_adapter.ClientPasswordCallback"/>
<jaxws:client id="m2mClientService"
serviceClass="de.vodafone.easypu.ws.EasyPUOrderServicePortType"
address="http://m2m.vodafone.de/speasy/services/EasyPUOrderService"
bindingId="http://www.w3.org/2003/05/soap/bindings/HTTP/">
<jaxws:outInterceptors>
<bean class="org.apache.cxf.ws.security.wss4j.WSS4JOutInterceptor">
<constructor-arg>
<map>
<entry key="action" value="UsernameToken Timestamp"/>
<entry key="passwordType" value="PasswordText"/>
<entry key="user" value="myusername"/>
<entry key="passwordCallbackRef">
<ref bean="myPasswordCallback"/>
</entry>
</map>
</constructor-arg>
</bean>
</jaxws:outInterceptors>
</jaxws:client>
That works quite well. But I did not understand why I have to provide the password via a callback handler instead of just providing it via configuration. The documentation says it is for security reasons, but I donĀ“t see why this should be more secure to have a callback handler that reads it from a property file (or worse has it hard coded in the callback).
So, could somebody explain this to me? Maybe the callback is intended for some magic stuff that I missed..
Thanks
Michel
The password callback is provided by Apache CXF as a mechanism for the client application to retrieve the credentials for the targeted webservice, which at runtime is likely to be stored in the database, configuration fiels, LDAP or some other store. This callback hook provides the flexibility to the application to retrieve the credentials from application specific configuration.
If password is stored in clear text in the configuration then this approach may not give you any extra security.
However having password stored as clear text in some configuration may have some security issues as there can be folks that may need access to this configuration and will be able to hold of password although it may not have been intended to.
Better is to store the encrypted password in the configuration. In this case, you need some code that will decrypt this password before it's use. Password callback will come to rescue in this scenario.

Spring JTA TransactionManager config: Supporting both Tomcat and JBoss

I have a web application using JPA and JTA with Spring. I would like to support both JBoss and Tomcat. When running on JBoss, I'd like to use JBoss' own TransactionManager, and when running on Tomcat, I'd like to use JOTM.
I have both scenarios working, but I now find that I seem to need two separate Spring configurations for the two cases. With JOTM, I need to use Spring's JotmFactoryBean:
<bean id="transactionManager"
class="org.springframework.transaction.jta.JtaTransactionManager">
<property name="userTransaction">
<bean class="org.springframework.transaction.jta.JotmFactoryBean"/>
</property>
</bean>
In JBoss, though, I just need to fetch "TransactionManager" from JNDI:
<bean id="transactionManager"
class="org.springframework.transaction.jta.JtaTransactionManager">
<property name="transactionManager">
<bean class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="resourceRef" value="true" />
<property name="jndiName" value="TransactionManager" />
<property name="expectedType"
value="javax.transaction.TransactionManager" />
</bean>
</property>
</bean>
Is there a way to configure this so that the appropriate TransactionManager - JBoss or JOTM - is used, without the need for two different configuration files?
I think you have missed the point of JNDI. JNDI was pretty much written to solve the problem you have!
I think you can take it up a level, so instead of using the "userTransaction" or "transactionManager from JNDI" depending on your situation. Why not add the "JtaTransactionManager" to JNDI. That way you push the configuration to the JNDI where it is supposed to be instead of creating even more configuration files [ like there aren't enough already ;) ].
You can use PropertyConfigurerPlaceholder to inject bean references as well as simple values.
For example if you call your beans 'jotm' and 'jboss' then you could inject your TM like:
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE">
<property name="location" value="classpath:/path/to/application.properties"/>
</bean>
<bean id="jotm">...</bean>
<bean id="jboss">...</bean>
<bean id="bean-requiring-transaction-manager">
<property name="transactionManager" ref="${transaction.strategy}"/>
</bean>
Then you can swap transaction managers using
transaction.strategy=jotm in a properties file
-Dtransaction.strategy=jotm as a system property
This is one possible approach. See my blog for a more complete example.
Hope this helps.
If you are using Spring 2.5 you can use <tx:jta-transaction-manager/>. I have not used it with JBoss but it should work for you according to section 9.8 Application server-specific integration from the Spring reference manual.
The <tx:jta-transaction-manager/> approach will look for a transaction manager in several default locations listed here. If your JBoss transaction manager is not in one of those locations, I suggest you move it, if possible, or move it in Tomcat so that both containers have their TM in the same JNDI location.
Just adding my experience here so I don't have to re-suffer the experience again.
As bmatthews68, Chochos and these posters have said, use <tx:jta-transaction-manager/> in your Spring bean file; it definitely provides the appropriate level of abstraction and there's no need to do anything extra on the Spring side.
As for Tomcat, I declared <Transaction factory="org.objectweb.jotm.UserTransactionFactory" jotm.timeout="60" /> in the default/shared conf/context.xml file, which binds to java:comp/UserTransaction. As this is one of the places searched for by Spring, you shouldn't need to do anything else.
One gotcha though: if like me you use Maven, make sure you exclude any dependencies on the javax.transaction:jta jar or set the scope to provided. Otherwise you will experience classloader issues.

Categories