Getting JAX-WS WebServices working in Spring Boot - spring-boot

I have some legacy JAX-WS #WebService annotated classes. I am trying to get this working in spring-boot. Been looking at https://jax-ws-commons.java.net/spring/ as a reference as well as http://docs.spring.io/spring/docs/current/spring-framework-reference/html/remoting.html.
My #SpringBootAnnotated class
#SpringBootApplication(exclude = {DataSourceAutoConfiguration.class, HibernateJpaAutoConfiguration.class})
public class SpringBootBooter extends SpringBootServletInitializer {
#Bean
public ServletRegistrationBean servletRegistrationBean() {
ServletRegistrationBean reg = new ServletRegistrationBean(new WSSpringServlet(),"/myws");
reg.setLoadOnStartup(1);
return reg;
}
public static void main(String args[]) throws Exception {
SpringApplication.run(new Object[] {
SpringBootBooter.class,
new ClassPathResource("myLegacyAppContextWithWSBean.xml")
}, args);
}
#Override
public void onStartup(final ServletContext servletContext) throws ServletException {
super.onStartup(servletContext);
servletContext.addListener(new WSServletContextListener());
}
}
My XML config for the WS implementation class
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:ws="http://jax-ws.dev.java.net/spring/core"
xmlns:wss="http://jax-ws.dev.java.net/spring/servlet"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://jax-ws.dev.java.net/spring/core
http://jax-ws.java.net/spring/core.xsd
http://jax-ws.dev.java.net/spring/servlet
http://jax-ws.java.net/spring/servlet.xsd">
<wss:binding url="/myws">
<wss:service>
<ws:service bean="#mywsbean" />
</wss:service>
</wss:binding>
<bean id="mywsbean" class="com.items.MyWsBean">
</bean>
</beans>
When everything boots up, I go to localhost:8080/myws and just get back "404 Not Found: Invalid Request".
Just not sure what I am missing, its like something is not parsing those wss:binding XML declarations to tie together these servlet requests to the bean, and I am not sure how to do this in spring-boot.
This appears in logs when I first hit that mapped URI
Jul 15, 2015 9:40:18 AM com.sun.xml.ws.transport.http.servlet.WSServletDelegate <init>
INFO: WSSERVLET14: JAX-WS servlet initializing
thanks

Your solution appears rather complex. You can get a JAX-WS service running with Spring Boot, using only
These Gradle dependencies:
dependencies {
compile "org.springframework.boot:spring-boot-starter-actuator"
compile "org.springframework.boot:spring-boot-starter-web"
compile "org.springframework.boot:spring-boot-starter-jersey"
}
This configuration class (Groovy):
import org.glassfish.jersey.server.ResourceConfig
import org.springframework.stereotype.Component
#Component
class JerseyConfig extends ResourceConfig {
JerseyConfig() {
register(MyResource)
}
}
This resource class:
import org.springframework.stereotype.Component
import javax.ws.rs.GET
import javax.ws.rs.Path
import javax.ws.rs.Produces
import javax.ws.rs.core.Context
import javax.ws.rs.core.MediaType
#Component
#Path("/foo")
class MyResource {
#GET
#Produces(MediaType.APPLICATION_JSON)
public Map bar() {
return ["hello":"world"]
}
}
and this:
import org.springframework.boot.SpringApplication
import org.springframework.boot.autoconfigure.SpringBootApplication
#SpringBootApplication
class DemoJaxWSService {
static void main(String[] args) {
SpringApplication.run DemoJaxWSService, args
}
}
Your endpoint will be available at localhost:8080/foo

Related

Spring Cache in MVC - Possible to lookup with autowiring?

I see that when the application starts up my singleton cache is created
DEBUG Creating CGLIB proxy: target source is SingletonTargetSource for
target object [com.abc.xyz.util.CacheUtil#14e3dd3] DEBUG Unable to
apply any optimizations to advised method: public java.util.Map
But how do I lookup the value using autowiring as when I attempt, it does not hit the singleton created and creates a new instance of CacheUtil.
CacheUtil.java [This class is annotated with #Component]
public Map getSelectOptions(String codeType) {
System.out.println("Cache Breached!!!");
HashMap selectOpts = new HashMap();
Vector<MyTableDO> vCodeMap = null;
vCodeMap = MyTableDO.getCodesFromDatabase(codeType, "LookupCacheUtil");
if(vCodeMap == null || vCodeMap.size() == 0) return selectOpts;
vCodeMap.forEach(codeMap -> selectOpts.put(codeMap.getCodeValue(), codeMap.getCodeDesc()));
return selectOpts;
}
My spring config xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<context:component-scan base-package="com.abc.xyz" />
<context:annotation-config />
<bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"/>
<bean id="cacheUtil" class="com.abc.xyz.util.CacheUtil" />
</beans>
Class Invoking the Cached method
#Autowired
#Qualifier("cacheUtil")
protected CacheUtil cacheUtil;
public Map getSelectOptions(String codeType) {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(MyApplication.class);
//ctx.refresh();
CacheUtil lkp = (CacheUtil) ctx.getBean(CacheUtil.class);
ctx.close();
System.out.println("App Context lookupCacheUtil -"+lkp); // Not the same object of Spring Cache and comes to be new instance on every call
System.out.println("Autowired lookupCacheUtil -"+cacheUtil); // Always comes to be NULL
return lkp.getSelectOptions(codeType);
}
}
MyApplication class
#SpringBootApplication
#EnableCaching
public class MyApplication extends SpringBootServletInitializer{
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(MyApplication.class);
}
#Override
public void onStartup(ServletContext container) {
XmlWebApplicationContext context = new XmlWebApplicationContext();
context.setConfigLocation("/WEB-INF/config/spring-servlet.xml");
//using servlet 3 api to dynamically create spring dispatcher servlet
ServletRegistration.Dynamic dispatcher = container.addServlet("spring", new DispatcherServlet(context));
dispatcher.setLoadOnStartup(2);
dispatcher.addMapping("/");
}
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
}
On detailed analysis, my understanding of Autowired become more refined. Thanks to this link.
In my case, I had autowired 'CacheUtil' on a form bean. It appears that the form beans are not being managed by spring or at least in this case. The same autowired works normally in a controller which is managed by Spring.
So I to work around by fetching the Spring Cache 'Proxy' version of CacheUtil from the Application Context. Below code snippet should help (method getInstance()):
import org.springframework.beans.BeansException;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
#Component("MyCache")
public class CacheUtil implements ApplicationContextAware{
private static ApplicationContext appContext;
#Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
// TODO Auto-generated method stub
appContext = applicationContext;
}
/**
* Method to fetch the shared instance of the Spring Cache Object that helps reach the
* Cache that resides in Application Context.
*
* #return Singleton shared instance of the Spring Cache Proxy of this class CacheUtil
*/
public static CacheUtil getInstance() {
CacheUtil appCache = appContext.getBean("MyCache", CacheUtil.class);
if(appCache != null) return appCache;
return new CacheUtil();
}

how to resolve my BeansException in spring

i am new to spring technology.I am trying to create simple spring standalone application using j2ee container.
for that i added 4 jar files.
1)commons-loggins-1.3 jar
2)spring_bean_3.0.5
3)spring_core_3.0.0
4)Spring_context_3.0.2
i am tring to create application context instance in my client class.i am getting following error.
Exception in thread "main" java.lang.Error: Unresolved compilation problems:
The type org.springframework.beans.BeansException cannot be resolved. It is indirectly referenced from required .class files
The constructor ClassPathXmlApplicationContext(String) refers to the missing type BeansException
at test.Core_J2ee_Client.main(Core_J2ee_Client.java:12)
This is my code.
this is my client class.
package test;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import beans.Test;
public class Core_J2ee_Client {
public static void main(String[] args) {
ConfigurableApplicationContext ap = new ClassPathXmlApplicationContext("resource/spring.xml");
}
}
This is my pojo class.
package beans;
public class Test {
public Test(){
System.out.println("this is test cons---");
}
public void hello(){
System.out.println("this is hello method");
}
}
This is my spring.xml file.
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
"http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<bean id="t" class="beans.Test">
</bean>
</beans>

How to load Spring applicationContext into Jersey Application

I'm creating a Jersey JAX-RS web service with the following:
package com.mycompany.rest.config;
import java.util.Set;
import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;
#ApplicationPath("")
public class ApplicationConfig extends Application {
#Override
public Set<Class<?>> getClasses() {
return getRestResourceClasses();
}
private Set<Class<?>> getRestResourceClasses() {
Set<Class<?>> resources = new java.util.HashSet<Class<?>>();
resources.add(com.mycompany.rest.controllers.UserController.class);
return resources;
}
}
However, when I try and integrate a spring applicationContext such as the following :
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="com.mycompany.rest.user"/>
<bean id="userService" class="com.mycompany.rest.user.UserServiceImpl" />
</beans>
I get null pointers from my controller class for the userService being loaded by the bean pasted above. I'm assuming this is because the application context is not being loaded into the Jersey application.
Is there a way of doing this?
If you want to inject Spring beans into your Jersey resource classes, you need to add jersey-spring3 dependency to your class path. see https://jersey.java.net/documentation/latest/spring.html
An hello-world example can be found at https://github.com/jersey/jersey/tree/2.19/examples/helloworld-spring-webapp
I had the same problem, and i fixed it by adding #autowired to my service, and extending SpringBeanAutowiringSupport like the following :
#Path("/mails")
public class MailController extends SpringBeanAutowiringSupport{
#Autowired
private MailService mailService;
#GET
#Path("/{code}")
#Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
public String getMails(#PathParam("code") String code) throws Exception {
//function logic
}
Note that this is working without integrating jersey-springx.jar
And I'm using Spring 3 along with jersey-bundle-1.19.1.jar

No unique bean of type is defined: expected single bean but found 0:

I have one spring based standalone project (PTSJMSProxy). I refer http://sahits.ch/blog/?p=2326
In the PTSJMSProxy I have followings.
1) SimpleWriterService.java
package com.test;
import org.springframework.stereotype.Service;
#Service
public class SimpleWriterService {
public void sayHello() {
System.out.println("Hello Spring DI service!");
}
}
2) ComponentConsumer.java
package com.test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
#Component
public class ComponentConsumer {
#Autowired
private SimpleWriterService service;
public void consume() {
service.sayHello();
}
}
3) ProxyJMSClient.java
package com.test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class ProxyJMSClient {
// I commented some portions,but working fine
// Example #Autowired and also in the constructure
// #Autowired
private ComponentConsumer consumer;
public ProxyJMSClient() {
ApplicationContext context = new ClassPathXmlApplicationContext(
"applicationContext.xml");
// AutowireCapableBeanFactory acbFactory =
// context.getAutowireCapableBeanFactory();
// acbFactory.autowireBean(this);
consumer = context.getBean(ComponentConsumer.class);
}
public void callMyJMSClient() {
this.consumer.consume();
}
}
4) Test.java
package com.test;
public class Test {
public static void main(String[] args) {
(new ProxyJMSClient()).callMyJMSClient();
}
}
5) applicationContext.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
<tx:annotation-driven />
<context:annotation-config />
<context:component-scan base-package="com.test" />
</beans>
Now when I invoke Test.java from eclipse Run As -Java Application I get the expected out put.
Output - Hello Spring DI service!
=============================================================================
Now I created the Jar with Eclipse export as Jar. Jar Name -PTSJMSProxy.jar
===============================================================================
My objective is to use this jar from a non spring java project
===============================================================================
I created another java project in eclipse "TestProxy"
In that project I add all the required Spring Jar and PTSJMSProxy.jar
Created TestJMSProxy.java class
package com.proxy.test;
import com.wiley.fts.ProxyJMSClient;
public class TestJMSProxy {
public static void main(String[] args) {
(new ProxyJMSClient()).callMyJMSClient();
}
}
When I run - I get following exceptions
log4j:WARN No appenders could be found for logger (org.springframework.context.support.ClassPathXmlApplicationContext).
log4j:WARN Please initialize the log4j system properly.
Exception in thread "main" org.springframework.beans.factory.NoSuchBeanDefinitionException: No unique bean of type [com.test.ComponentConsumer] is defined: expected single bean but found 0:
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:269)
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1083)
at com.wiley.fts.ProxyJMSClient.<init>(ProxyJMSClient.java:19)
at com.proxy.test.TestJMSProxyJar.main(TestJMSProxyJar.java:8)
How can I resolve this
NOTE: -
PTSJMSProxy is a spring based project - which has its own applicationContext.xml (Refer point no -5)
TestProxy is a NON Spring Java project - where I use PTSJMSProxy Jar
PTSJMSProxy Jar folder structure
PTSJMSProxy jar contains com,META-INF and applicationContext.xml under same level
The problem is resolved.
This is due to the loading problem of spring configuration xml file.
Code
String fileUrl = PTSJMSProxyClient.class.getClassLoader()
.getResource(SPRING_JMS_CFG_FILE).toString();
LOG.info("Spring jmsContext.xml file path :" +fileUrl);
xmlApplicationContext = new ClassPathXmlApplicationContext(fileUrl);
AutowireCapableBeanFactory acbFactory = xmlApplicationContext
.getAutowireCapableBeanFactory();
acbFactory.autowireBean(this);
client = xmlApplicationContext.getBean(MessageSenderImpl.class);
Sometime it also happens when you define basePackages wrongly inside #ComponentScan annotation like:
#ComponentScan("com.whodesire.model", "com.whodesire.util")
here the above one will considered as single package, if there are multiple packages to scan within your project, then you must mention packages like String[]
#ComponentScan( { "com.whodesire.model" , "com.whodesire.util" } )

unable to use Spring Advice(#Before) using annotations

I am new to springs and trying to run a simple java application with java advices....
xml file...
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd">
<aop:aspectj-autoproxy>
<aop:include name="com.cts.two.Advices"/>
</aop:aspectj-autoproxy>
<context:annotation-config/>
<context:component-scan base-package="com.cts.two"></context:component-scan>
</beans>
Advice Class
package com.cts.two;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
#Aspect
public class Advices implements Adv{
#Pointcut("execution(* com.cts.two.*.*(..))")
public void advice(){
}
#Before("advice()")
public void before(JoinPoint name) throws Throwable{
System.out.println("inside advices");
/*System.out.println(name.getClass() + " this is get class");
System.out.println(name.getSignature().getName() + " this is the get signatue and get name");*/
}
}
class on which advice needs to be applied...I want the before method of Advice class to be executed before below mentioned test() method
package com.cts.two;
import org.springframework.stereotype.Component;
#Component
public class ClassA {
private ClassB b= new ClassB();
public void setB(ClassB b) {
this.b = b;
}
public void test(){
System.out.println("inside classA test");
//b.test();
}
}
caller of methods/test class/main class
package com.cts.two;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class CallerAB {
/**
* #param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
ApplicationContext context = new ClassPathXmlApplicationContext(
"AllAnnotations.xml");
ClassA calledA = (ClassA) context.getBean("classA");
calledA.test();
}
}
the problem is that when I run the code directly the test method of class A is executed but the advice is not...
Kindly advice..
Am i missing something ???
AspectJ 1.6.12 jar is also added...
Aspects should be decalred as beans.
#Aspect doesn't do it automatically, <aop:include> doesn't do it as well (it sets additional restriction on beans that can be used as aspects).
So, you need
#Aspect
#Component
public class Advices implements Adv { ... }
and don't need <aop:include>.
As mentioned in the answer from #axtavt you need to add the #Component annotation. But you also need to remove the <aop:include>. Your spring wiring xml should just be:
<aop:aspectj-autoproxy/>
<context:annotation-config/>
<context:component-scan base-package="com.cts.two"/>
As stated in the spring AOP documentation, the name attribute in the <aop:include> element is supposed to be a bean name, not a class name. Specifying a bean explicitly overrides Spring's auto-detection and specifying it incorrectly means that there is no aspect used at all.

Resources