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

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"/>

Related

How to consume an EJB in Spring?

I'm trying to inject the EJB with a Spring application in a Websphere server to call his methods.
I downloaded the EJB's jar and added it as a Library in the project.
The jar exposes a Remote, which is an interface.
1: EJB Jar in Libraries
Then I tried to make Spring understand that it is an EJB.
I put this inside web.xml
<description />
<ejb-ref-name>ejb/AberturaEJBRemoteRef</ejb-ref-name>
<ejb-ref-type>Session</ejb-ref-type>
<home />
<remote>
br.com.zzz.xxx.servcaptura.abertura.ejb.AberturaEJBRemote
</remote>
<ejb-link>AberturaEJB</ejb-link>
</ejb-ref>
Then I tried these two configurations at app.context:
First attempt:
<jee:remote-slsb id="abertura" jndi- name="ejb/AberturaEJBRemoteRef#br.com.zzz.xxx.servcaptura.abertura.ejb.AberturaEJBRemote"
business-interface="br.com.zzz.xxx.servcaptura.abertura.ejb.AberturaEJBRemote"
home-interface="br.com.zzz.xxx.servcaptura.abertura.ejb.AberturaEJBRemote"
cache-home="false" lookup-home-on-startup="false"
refresh-home-on-connect-failure="true" />
Second attempt:
<bean id="abertura"
class="org.springframework.ejb.access.LocalStatelessSessionProxyFactoryBean" lazy-init="true">
<property name="jndiName" value="ejb/AberturaEJBRemoteRef" />
<property name="businessInterface" value="br.com.zzz.xxx.servcaptura.abertura.ejb.AberturaEJBRemote" />
</bean>
<bean id="acompanhamentoWebService" class="br.com.zzz.xxx.integracaosinistro.servacompws.webservice.AcompanhamentoWebService">
<property name="abertura">
<ref bean="abertura" />
</property>
</bean>
Inside a class, I'm doing this:
#Service
#WebService
public class AcompanhamentoWebService {
#Autowired(required = true)
private AberturaEJBRemote abertura;
...
The second one Spring can't understand that it is a bean.
On the first configuration attempt, with jee:remote-slsb, here I'm getting error after call the EJB method:
name: ejb/AberturaEJBRemoteRef#br.com.zzz.xxx.servcaptura.abertura.ejb.AberturaEJBRemote: First component in name AberturaEJBRemoteRef#br.com.zzz.xxx.servcaptura.abertura.ejb.AberturaEJBRemote not found. [Root exception is org.omg.CosNaming.NamingContextPackage.NotFound: IDL:omg.org/CosNaming/NamingContext/NotFound:1.0]
I really don't know if I am trying this correctly, cause I never work with EJB before.
Call the remote inside the jar is a correct approach?
What do you think I'm doing wrong?
Sorry for the bad English.
Thanks.
UPDATE
I founded an example and it seems that my approach is ok. But it missing an EJB configuration inside Websphere. To call the EJB remotely, I read that I will need the server informations where the EJB is stored and available.
And I don't have this information yet.
I think that I could access the methods from EJB directly from the jar. But I understood that it's not like this.
I will come back here when the problem was solved or another information appears.

Shiro annotation on OSGI

I run an OSGI application on Karaf 4.0.4.
This application is not a web application.
I configured Apache Shiro in order to login using a custom SecurityRealm that use the credentials stored in an SQL database. The SecurityManagerand the realm are configured using Blueprint
This part works fine.
I want to use annotations like:
#RequiresPermissions("doSomething")
#RequiresRoles("admin")
public void myMethodToDoSomething() {
...
}
Those annoations are never evaluated. (my security realm protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) method is never called.
After reading some Shiro documentation, I understand it doesn't work because I don't have the required interceptor as it's defined in the Shiro Spring turorial:
<!-- Enable Shiro Annotations for Spring-configured beans. Only run after -->
<!-- the lifecycleBeanProcessor has run: -->
<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator" depends-on="lifecycleBeanPostProcessor"/>
<bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
<property name="securityManager" ref="securityManager"/>
But as I'm not using spring in my application, those lines won't work.
You can create a blueprint namespace module. This can then hook into the blueprint beans to install an interceptor. As an example see the blueprint-authz module.

How does Spring start this app?

I'm parsing through some inherited code of a Java app that is deployed as a WAR file in JBOSS, and uses Spring, JMS, and HornetQ. I'm trying to figure out, for lack of a better phrase, what makes the app "go". Most of the Spring examples I've seen include an application with a main() method, which imperatively acts on the beans provided by the Spring context in some way. This application has no main(). As far as I can tell, this is what's happening:
The WAR file's web.xml uses a listener to launch Spring when the application starts in JBOSS, and passes it a config file
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:application-context.xml</param-value>
</context-param>
Spring then processes the application-context.xml file, which includes this snippet:
<bean id="jmsContainer"
class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="connectionFactory" ref="connectionFactory" />
<property name="destination" ref="destination" />
<property name="messageListener" ref="appListenerProxy" />
Through a couple more references in the application-context.xml, the "appListenerProxy" ultimately refers to a class in the application that implements SessionAwareMessageListener, which responds to messages on a queue.
The part that's tripping me up is that I don't see any kind of code to get the jmsContainer bean and do something with it. Is that a well-defined ID, such that the Spring framework is looking for it? And if so, is that documented somewhere (along with other IDs the framework might be looking for)? http://docs.spring.io/spring/docs/current/spring-framework-reference/html/jms.html seemed to be the closest I found, but it doesn't really specify whether that ID is just in the examples by convention, or if it's a meaningful string.
Thanks
Containers in spring are part of the framework core. The Framework will scan all the containers that implement a certain container interface, and initialize them.
This also relies on the Inversion of Control (IoC) principle.
For more information on IoC Container, check this page:
IoC Container
You don't really need to do anything with DefaultMessageListenerContainer bean, its frame work part.
The DefaultMessageListenerContainer bean establish JMS session with your JMS destination on application startup. When message are received in your destination it invokes the messageListener onMessage method- in your case appListenerProxy bean.
read here.

How to Create Service class Object in Spring

I am using ehcache in my project so when server start data of few table will be loaded into the cache ..in my application i am using Spring,Hibernate,JSF
I m using this configurationin applicationCOntext.xml file
<bean id="cacheManager" class="com.ccc.service.cache.CacheManager" init-method="init">
<property name="delay" value="${timer.delay}" />
</bean>
<bean id="companyCache" class="com.ccc.service.cache.clients.ValidCacheClient"/>
<context:component-scan base-package="com.ccc.spring" />
<context:annotation-config />
<context:spring-configured />
In Jsf Managed Bean i am creating Object of Service class like this
#ManagedProperty(value = "#{GlobalDataService}")
static GlobalDataService globalDataService;
But in ValidCacheClient.java how to create object of Service class? ValidCacheClient.java is not a manged class so how to create the Object of Service class?
You have two options:
Inject the necessary beans to be known from JSF as ServletContext attributes, so these beans will be treat by JSF as application scoped attributes. You can do this using Spring ServletContextAttributeExporter:
<bean class="org.springframework.web.context.support.ServletContextAttributeExporter">
<property name="attributes">
<map>
<entry key="globalDataService" value-ref="GlobalDataService" />
</map>
</property>
</bean>
Then you can inject it without problems in JSF:
#ManagedProperty(value = "#{globalDataService}")
GlobalDataService globalDataService; //no need to be static
Let Spring container manage the lyfecycle of JSF managed beans. With this approach, you may inject the springs beans using #Autowired. This is covered in Spring 3 + JSF 2 tutorials. Still, note that if you do this, you will lose access to JSF 2 view scope (crucial when working with ajax requests in the same view) because Spring still cannot support it. But this can be solved by creating a custom implementation for view scope, like Cagatay's
IMO I would use the latter approach rather than the former.
More info:
Set attributes of ServletContext in Spring 3.2 MVC configuration
Mkyong tutorial to integrate Spring 3 and JSF 2.0
Bean properties are shared across different sessions
Integration jsf, spring, hibernate. How to inject Spring beans into JSF managed beans?

JAX-RPC, Spring web services, and UnsupportedOperationCallException

I have a JAX-RPC web service that I am attempting to consume using Spring. This is my first time using Spring to consume a web service, so right now I'm just trying to get it to integrate with the JAX-RPC web service as a test.
The web service has several dozen operations in it, but for right now I only care about one. Here are the interfaces I've created on the Spring/client side:
public interface WSClient {
public boolean userExists(int userid);
}
public interface WSService {
//this method matches the method signature of the Web Service
public com.company.data.User getUser(int userid);
}
And here is my applicationContext.xml:
<bean id="WSClient" class="com.company.ws.test.WSClientImpl">
<property name="service" ref="myWebService"></property>
</bean>
<bean id="myWebService" class="org.springframework.remoting.jaxrpc.JaxRpcPortProxyFactoryBean">
<property name="serviceInterface" value="com.company.ws.test.WSService"/>
<property name="endpointAddress" value="http://1.2.3.4/web-service/data"/>
<property name="namespaceUri" value="http://www.company.com/wdsl"/>
<property name="serviceName" value="CompanyWebService"/>
<property name="username" value="username"/>
<property name="password" value="password"/>
<property name="maintainSession" value="true"/>
</bean>
Using this configuration of JaxRpcPortProxyFactoryBean, invoking the Service returns the following exception:
org.springframework.remoting.RemoteProxyFailureException: Invalid JAX-RPC call configuration; nested exception is operation style: "rpc" not supported
I've never fully understood the difference between RPC and document-style web services; however, I believe this web service is using RPC-style - so this exception confuses me.
Second, I'm confused on which properties I should be setting with JaxRpcPortProxyFactoryBean:
If I set the wsdlDocumentUrl property, I end up getting a HTTP 401 error as this web service sits behind HTTP Basic Authentication, and it seems Spring does not use the username/password properties when fetching the WSDL.
If I specify a PortInterface property (with a value of CompanyWebServiceInterfacePort), then I get a different Exception stating:
Failed to initialize service for JAX-RPC port [{http://www.company.com/wdsl}CompanyWebServiceInterfacePort]; nested exception is WSDL data missing, this operation is not available
In other words, it's telling me that the WSDL is missing - which I can't set since Spring won't use the username/password to fetch it from the server!
I'm not sure if any of this makes any sense, but in essence what I'm unsure of is:
For a JAX-RPC service, do I need to set the PortInterface property? Is this the path I should be going down?
Similiarly, does Spring need me to set the wsdlDocumentUrl property? If so, is there any way I can tell Spring which WSDL and get around the authentication problem?
I eventually solved this by saving a copy of the WSDL file locally, and, since JaxRpcPortProxyFactoryBean expects a java.net.URL for the wsdlDocumentUrl property, had to set it with a path like file:///c:/.../blah.wsdl.
This isn't really all that desireable, I would hate to have to put a file:/// URI in a Spring context file that might be deployed on a server, especially on a different platform - seems odd that this class behaves this way.
I'm guessing most people aren't using Spring aren't using JAX-RPC anyway.

Categories