How to access a huge JSON coming (from a spring RESTful Service) in a spring MVC app using RestTemplate - web-services

My Spring RESTful web service is returning a JSON form of-
[{"key1":"value1","key2":"value2","key3":"value3"},{"key4":"value4","key5":"value5","key6":"value6"}]
Now when my spring MVC app, try to access it, to show in a JSP then Exception occurs saying-no suitable HttpMessageConverter found Please help me where I going wrong.Here is my code-
Inside #Controller class of my spring MVC app calling the RESTful service
//**com.songs.controllers.FrontSongController.java**
</*
author Rohit Tiwari
*/>
#RequestMapping(value="/alls",method=RequestMethod.POST)
public String getAllSongs(ModelMap md)
{
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
HttpEntity<String> entity = new HttpEntity<String>(headers);
String url="http://localhost:7001/SongAppWS/songappWS/allsongsWS";
RestTemplate rt=new RestTemplate();
//SongResource.class is for representation on incoming JSON see below for its code
//This is the line no 48 that you will see in below browser logs
ResponseEntity<SongResource> listofallsongs=rt.exchange(url,HttpMethod.GET,entity, SongResource.class);
md.addAttribute("listname", "Songs available in the repository:");
System.out.println("Response Entity object= "+listofallsongs);
System.out.println("Response Entity body= "+listofallsongs.getBody().toString());
return "Sucess";
}
Inside config-servlet.xml of my spring MVC app calling the RESTful service
<context:component-scan base-package="com.songs.controllers" />
<mvc:annotation-driven />
<context:annotation-config/>
<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping"></bean>
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"></bean>
<bean class="org.springframework.web.client.RestTemplate">
<property name="messageConverters">
<list>
<bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"/>
</list>
</property>
</bean>
<bean id="viewResolver" class="org.springframework.web.servlet.view.UrlBasedViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView" />
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>
Inside SongResource.java of my spring MVC app, which I am trying to use for converting the coming JSON to my SongResource.class object, that my spring MVC app can use in a jsp
//**com.songs.service.resource.SongResource.java**
public class SongResource
{
private String name;
private String film;
private String singer;
public SongResource(String name,String film,String singer)
{
this.name=name;
this.film=film;
this.singer=singer;
}
//setter & getters of all above
}
On calling the spring REST service from my spring MVC app the browser is saying as below-
Error 500--Internal Server Error
org.springframework.web.client.RestClientException: Could not extract response: no suitable HttpMessageConverter found for response type [com.songs.service.resource.SongResource] and content type [application/json]
at org.springframework.web.client.HttpMessageConverterExtractor.extractData(HttpMessageConverterExtractor.java :77)
at org.springframework.web.client.RestTemplate$ResponseEntityResponseExtractor.extractData(RestTemplate.java:619)
at org.springframework.web.client.RestTemplate$ResponseEntityResponseExtractor.extractData(RestTemplate.java:1)
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:446)
at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:401)
at org.springframework.web.client.RestTemplate.exchange(RestTemplate.java:377)
at com.songs.controllers.FrontSongController.getAllSongs(FrontSongController.java:48)
//and so on

Try this, hope it will help you
#RequestMapping(value="/alls",method=RequestMethod.POST)
public String getAllSongs(ModelMap md)
{
String url="http://localhost:7001/SongAppWS/songappWS/allsongsWS";
RestTemplate rt=new RestTemplate();
SongResource[] songRs = template.getForObject(url, SongResource[].class);
List<SongResource> songs = Arrays.asList(songRs);
md.addAttribute("listname", "Songs available in the repository:");
md.addAttribute("listValues", songs);
return "Sucess";
}

Related

I am able to write a javax.jws.WebService successfully. However I do not know exactly how to write a web service client for same in java

I have written Webservice in java which has successfully created WSDL. I am stuck in writing a webservice client for my webservice in java. I would like to use my webservice from some jsp classes. How do i do it?
#WebService
public interface AddService {
double getMultipicationResult(double M1, double M2);
}
#WebService(endpointInterface = "com.sample.AddService")
public class AddServiceImpl implements AddService {
public AddServiceImpl() {
}
#Override
public double getMultipicationResult(double M1, double M2) {
M1 = M1*M2;
return M1;
}
}
I have written the client something like :-
public class AddServiceClient {
private AddServiceClient() {
}
public static void main(String args[]){
{
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new String[] {"SpringClientWebServices.xml"});
AddService client = (AddService)context.getBean("client");
double response = 0.0;
response = client.getMultipicationResult(10.0, 20.5);
}
}
and SpringClientWebServices.xml is as follows :-
<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"
xmlns:jdbc="http://www.springframework.org/schema/jdbc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/jdbc
http://www.springframework.org/schema/jdbc/spring-jdbc-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<bean id="client" class="com.sample.AddService"
factory-bean="clientFactory" factory-method="create"/>
<bean id="clientFactory" class="org.apache.cxf.jaxws.JaxWsProxyFactoryBean">
<property name="serviceClass" value="com.sample.AddService"/>
<property name="address" value="http://localhost:8080/sample/services/Addition"/>
</bean>
</beans>
I am getting exception as follows:-
Exception in thread "main" org.springframework.beans.factory.CannotLoadBeanClassException: Cannot find class [org.apache.cxf.jaxws.JaxWsProxyFactoryBean] for bean with name 'clientFactory' defined in class path resource [SpringClientWebServices.xml]; nested exception is java.lang.ClassNotFoundException: org.apache.cxf.jaxws.JaxWsProxyFactoryBean
First of all you are missing the CXF jars as evident from the ClassNotFoundException. Please include the cxf jars.
Second regarding using the service in JSPs then you have to first initialize the Spring container via web.xml and not via main method. Use Spring MVC and implement controller which makes calls to webservice and provide data to the JSP.
If you want to consume a service directly from the JSP, consider a JavaScript client like mentioned: http://cxf.apache.org/docs/javascript-client-samples.html
I prefer to use a jar that contains the service interface and create a dynamic Spring client using CXF and Spring in a separate jar, then bring in both f those dependencies. This is also documented in the CXF site.

How can i have two separate web services with identical name space and local name requests be routed to different end points?

I'm attempting to create 2 separate web services, both within one spring deployment, both with the wsdl's being generated from the same xsd schemas, yet have them be routed to two separate end points so i can handle the requests differently in the separate contexts.
Ex:
Webservice 1: subset of access, lower privileges and security constraints
Webservice 2: higher privileges
<sws:dynamic-wsdl id="spml-readonly"
portTypeName="SpmlReadOnlyService"
locationUri="SpmlReadOnly">
<sws:xsd location="/WEB-INF/xsd/spml/pstc_spmlv2_core.xsd"/>
</sws:dynamic-wsdl>
<sws:dynamic-wsdl id="spml-crud"
portTypeName="SpmlCrudService"
locationUri="SpmlCrud">
<sws:xsd location="/WEB-INF/xsd/spml/pstc_spmlv2_core.xsd"/>
<sws:xsd location="/WEB-INF/xsd/spml/pstc_spmlv2_search.xsd"/>
<sws:xsd location="/WEB-INF/xsd/spml/pstc_spmlv2_batch.xsd"/>
</sws:dynamic-wsdl>
Now since both wsdls are based off of the same xsds, the 'namespace' and 'localPart" of the requests come across the wire identical, regardless of which web service i'm hitting (/SpmlReadOnly or /SpmlCrud).
Therefore, that's ruling out the deprecated PayloadRootQNameEndpointMapping since the localPart and namespace are still identical, etc,... and my current config simply routes the requests to the same endpoint method handler, and i have no way of distinguishing which web service was called:
#PayloadRoot(namespace = NAMESPACE_URI, localPart = "lookupRequest")
#ResponsePayload
public Source handleLookupRequest(SoapMessage message) throws Exception {
...
}
Is what I'm able to do even possible? If the xsd's are shared and have identical namespaces at the root of the schema, and the same localPart method requests, will there ever be a way to distinguish between them and map to two different end points? Any information on this would be useful! I'm hoping i don't have to set up two separate .wars and deploy them separately with their own code bases on a server!
Thanks,
Damian
You need something that combines URI and PayloadRoot mapping. Unfortunately Spring-Ws doesn't have something like this. But because it's very extensible it's really easy to achieve this.
TL;DR
See This branch at GitHub for working example
Details
You need to create mapping of combined URI+QName to org.springframework.ws.server.endpoint.MethodEndpoint instances. Also you should minimize the code which would duplicate existing Spring-Ws functions.
So 1) You need to explicitly configure Spring-Ws annotations without using <sws:annotation-driven />:
This is your requirement (with my schemas):
<ws:dynamic-wsdl id="spml-readonly" portTypeName="SpmlReadOnlyService" locationUri="SpmlReadOnly">
<ws:xsd location="classpath:springws/model/schema.xsd" />
</ws:dynamic-wsdl>
<ws:dynamic-wsdl id="spml-crud" portTypeName="SpmlCrudService" locationUri="SpmlCrud">
<ws:xsd location="classpath:springws/model/schema.xsd" />
<ws:xsd location="classpath:springws/model/schema2.xsd" />
</ws:dynamic-wsdl>
This is all you need to do by hand which normally is configured by <sws:annotation-driven /> (one adapter with one JAXB marshaller):
<bean class="org.springframework.ws.server.endpoint.adapter.DefaultMethodEndpointAdapter">
<property name="methodArgumentResolvers">
<list>
<ref local="marshallingPayloadMethodProcessor"/>
</list>
</property>
<property name="methodReturnValueHandlers">
<list>
<ref local="marshallingPayloadMethodProcessor"/>
</list>
</property>
</bean>
<bean id="marshallingPayloadMethodProcessor" class="org.springframework.ws.server.endpoint.adapter.method.MarshallingPayloadMethodProcessor">
<property name="marshaller" ref="marshaller" />
<property name="unmarshaller" ref="marshaller" />
</bean>
<bean id="marshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
<property name="contextPaths">
<list>
<value>springws.model</value>
</list>
</property>
</bean>
This is custom mapping:
<bean class="springws.PathAndPayloadRootAnnotationEndpointMapping" />
And 2) You should create your own mapping
public class PathAndPayloadRootAnnotationEndpointMapping extends PayloadRootAnnotationMethodEndpointMapping
{
#Override
protected QName getLookupKeyForMessage(MessageContext messageContext) throws Exception
{
String urlPart = "";
QName payloadRootPart = super.getLookupKeyForMessage(messageContext);
TransportContext transportContext = TransportContextHolder.getTransportContext();
if (transportContext != null) {
WebServiceConnection connection = transportContext.getConnection();
if (connection != null && connection instanceof HttpServletConnection) {
String requestURI = ((HttpServletConnection)connection).getHttpServletRequest().getRequestURI();
String contextPath = ((HttpServletConnection)connection).getHttpServletRequest().getContextPath();
urlPart = requestURI.substring(contextPath.length());
}
}
return new QName(payloadRootPart.getNamespaceURI(), urlPart + "/" + payloadRootPart.getLocalPart());
}
#Override
protected List<QName> getLookupKeysForMethod(Method method)
{
List<QName> result = new ArrayList<QName>();
RequestMapping rm = AnnotationUtils.findAnnotation(method.getDeclaringClass(), RequestMapping.class);
String urlPart = rm == null || rm.value().length != 1 ? "" : rm.value()[0];
List<QName> methodPart = super.getLookupKeysForMethod(method);
for (QName qName : methodPart) {
result.add(new QName(qName.getNamespaceURI(), urlPart + "/" + qName.getLocalPart()));
}
return result;
}
}
which extends org.springframework.ws.server.endpoint.mapping.PayloadRootAnnotationMethodEndpointMapping. And all it does is extending the keys (QNames of payload root elements) of messages with the information extracted from the endpoint URI. I've used Spring's #org.springframework.web.bind.annotation.RequestMapping annotation for that, but someone thinking it's a hack may create his/her own annotation.
So for endpoint like this:
#org.springframework.ws.server.endpoint.annotation.Endpoint
#RequestMapping("/ws/SpmlReadOnly")
public class Endpoint1
{
#ResponsePayload
#PayloadRoot(namespace = "urn:test", localPart = "method1Request")
public Response2 method(#RequestPayload Request1 request) throws Exception
{
return new Response2("e1 m1");
}
}
the key is not:
namespace = urn:test
localName = method1Request
but this:
namespace = urn:test
localName = /ws/SpmlReadOnly/method1Request
The protected QName getLookupKeyForMessage(MessageContext messageContext) method ensures that the mapping URI is independent of the WAR context, the application is deployed at.

EntityManagerFactory not being injected using #PersistenceUnit

I'm a java beginner. I'm in trouble to configure a persistance unit using JTA transactions.
I need to use a PostgreSQL database that is already defined, configured and populated. Using netbeans, i created the persistance.xml and glassfish-resources.xml as fallows:
<persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
<persistence-unit name="WellWatcherPU" transaction-type="JTA">
<jta-data-source>WellWatcherDB</jta-data-source>
<exclude-unlisted-classes>false</exclude-unlisted-classes>
<properties>
<property name="eclipselink.logging.logger" value="org.eclipse.persistence.logging.DefaultSessionLog"/>
<property name="eclipselink.logging.level" value="FINE"/>
</properties>
</persistence-unit>
</persistence>
and
<resources>
<jdbc-connection-pool allow-non-component-callers="false" associate-with-thread="false" connection-creation-retry-attempts="0" connection-creation-retry-interval-in-seconds="10" connection-leak-reclaim="false" connection-leak-timeout-in-seconds="0" connection-validation-method="auto-commit" datasource-classname="org.postgresql.ds.PGSimpleDataSource" fail-all-connections="false" idle-timeout-in-seconds="300" is-connection-validation-required="false" is-isolation-level-guaranteed="true" lazy-connection-association="false" lazy-connection-enlistment="false" match-connections="false" max-connection-usage-count="0" max-pool-size="32" max-wait-time-in-millis="60000" name="post-gre-sql_geowellex_geowellexPool" non-transactional-connections="false" pool-resize-quantity="2" res-type="javax.sql.DataSource" statement-timeout-in-seconds="-1" steady-pool-size="8" validate-atmost-once-period-in-seconds="0" wrap-jdbc-objects="false">
<property name="serverName" value="localhost"/>
<property name="portNumber" value="5432"/>
<property name="databaseName" value="DBNAME"/>
<property name="User" value="USER"/>
<property name="Password" value="PASSWORD"/>
<property name="URL" value="jdbc:postgresql://localhost:5432/DBNAME"/>
<property name="driverClass" value="org.postgresql.Driver"/>
</jdbc-connection-pool>
<jdbc-resource enabled="true" jndi-name="WellWatcherDB" object-type="user" pool-name="post-gre-sql_geowellex_geowellexPool"/>
</resources>
And this is how i get the EntityManagerFactory and EntityManager (as used in the netBeans example)
public class EUserDao {
#Resource
private UserTransaction utx = null;
#PersistenceUnit(unitName = "WellWatcherPU")
private EntityManagerFactory emf = null;
public EntityManager getEntityManager() {
return emf.createEntityManager(); <-------- NullPointerException here
}
public EUser getOne(long userId){
EntityManager em = getEntityManager();
try {
return em.find(EUser.class, userId);
} finally {
em.close();
}
}
EDIT:
And here is my glassfish deploy log:
Informações: [EL Config]: 2012-05-10 12:01:13.534--ServerSession(2017352940)--Connection(1901223982)--Thread(Thread[admin-thread-pool-4848(5),5,grizzly-kernel])--connecting(DatabaseLogin(
platform=>DatabasePlatform
user name=> ""
connector=>JNDIConnector datasource name=>null
))
Informações: [EL Config]: 2012-05-10 12:01:13.534--ServerSession(2017352940)--Connection(1462281761)--Thread(Thread[admin-thread-pool-4848(5),5,grizzly-kernel])--Connected: jdbc:postgresql://localhost:5432/geowellex?loginTimeout=0&prepareThreshold=0
User: geowellex
Database: PostgreSQL Version: 9.1.3
Driver: PostgreSQL Native Driver Version: PostgreSQL 8.3 JDBC3 with SSL (build 603)
Informações: [EL Config]: 2012-05-10 12:01:13.534--ServerSession(2017352940)--Connection(766700859)--Thread(Thread[admin-thread-pool-4848(5),5,grizzly-kernel])--connecting(DatabaseLogin(
platform=>PostgreSQLPlatform
user name=> ""
connector=>JNDIConnector datasource name=>null
))
What's wrong?
Most likely problem is that your EUserDao is just regular class. Injection works only for container managed classes. Annotations like #PersistenceUnit and #Resource are not processed for normal classes.
Following types of classes are container managed classes (and in those #PersistenceUnit can be used):
Servlet: servlets, servlet filters, event listeners
JSP: tag handlers, tag library event listeners
JSF: scoped managed beans
JAX-WS: service endpoints, handlers
EJB: beans, interceptors
Managed Beans: managed beans
CDI: CDI-style managed beans, decorators
Java EE Platform: main class (static), login callback handler
I see that in your code declare:
private EntityManagerFactory emf = null;
but never create one... like this
emf = Persistence.createEntityManagerFactory("WellWatcherPU");
Thats why you get a Null Pointer Exception when use the object!
public EntityManager getEntityManager() {
return emf.createEntityManager(); <-------- NullPointerException here
}

Spring Web Service Template: Add username token

I have a web app that acts as a client to a Jax-WS web service implemented using Spring WS. The Spring WS is configured to require a username token in the SOAP header. In the web app I plan to use the Spring web service template but I can't seem to find any examples which show how to add a UsernameToken to the outgoing request.
Can someone point me in the right direction?
Thanks.
You have to use Interceptors. See Chapter 7. Securing your Web services with Spring-WS.
The configuration would be something like this
<bean id="webServiceTemplate" class="org.springframework.ws.client.core.WebServiceTemplate">
<property name="marshaller" ref="marshaller" />
<property name="unmarshaller" ref="marshaller" />
<property name="defaultUri"
value="http://localhost:8080/ws-demo/myws" />
<property name="interceptors">
<list>
<ref bean="wsSecurityInterceptor" />
</list>
</property>
</bean>
<bean id="wsSecurityInterceptor" class="org.springframework.ws.soap.security.wss4j.Wss4jSecurityInterceptor">
<property name="securementActions" value="UsernameToken"/>
<property name="securementUsername" value="Ernie"/>
<property name="securementPassword" value="Bert"/>
</bean>
in addition to jddsantaella's answer, the client class can use SAAJ to add username token in the SOAP header:
OrganisationPortfolioRequest request = WS_CLIENT_FACTORY.createOrganisationsPortfolioRequest();
OrganisationPortfolioResponse response;
response = (OrganisationPortfolioResponse) webServiceTemplate.marshalSendAndReceive(request,
new WebServiceMessageCallback() {
public void doWithMessage(WebServiceMessage message) throws IOException, TransformerException {
SaajSoapMessage soapMessage = (SaajSoapMessage) message;
SoapEnvelope envelope = soapMessage.getEnvelope();
envelope.addNamespaceDeclaration("soapenv", "http://schemas.xmlsoap.org/soap/envelope/");
envelope.addNamespaceDeclaration("s", "http://company.com/ws/security.xsd");
SoapHeaderElement username = soapMessage.getSoapHeader().addHeaderElement(new QName("http://company.com/ws/security.xsd", "username", "s"));
username.setText(getCurrentUser.getUsername());
}
});
response.getResults();
Above given answer is used for xml.
I mention here annotation base configuration for usernameToken security policy for web service.
Add this configuration with spring boot client
#Bean
public WebServiceTemplate webServiceTemplate() {
WebServiceTemplate webServiceTemplate = new WebServiceTemplate();
webServiceTemplate.setMarshaller(marshaller());
webServiceTemplate.setUnmarshaller(marshaller());
webServiceTemplate.setDefaultUri("http://localhost:8080/ws");
webServiceTemplate.setInterceptors(new ClientInterceptor[] {wsSecurityInterceptor()});
return webServiceTemplate;
}
#Bean
public Wss4jSecurityInterceptor wsSecurityInterceptor() {
Wss4jSecurityInterceptor wss4jSecurityInterceptor = new Wss4jSecurityInterceptor();
wss4jSecurityInterceptor.setSecurementActions(WSHandlerConstants.TIMESTAMP + " " + WSHandlerConstants.USERNAME_TOKEN);
wss4jSecurityInterceptor.setSecurementPasswordType(WSConstants.PW_TEXT);
wss4jSecurityInterceptor.setSecurementUsername("user");
wss4jSecurityInterceptor.setSecurementPassword("password");
return wss4jSecurityInterceptor;
}

property injection in apache cxf using spring

I have the following class
public class HeaderClass{
#Resource
private WebServiceContext webServiceContext;
public String getUserAgent() {
MessageContext msgCtx = webServiceContext.getMessageContext();
HttpServletRequest request = (HttpServletRequest)msgCtx.get(AbstractHTTPDestination.HTTP_REQUEST);
return request.getHeader("user-agent")
}
In my service bean class I want to inject this HeaderClass, so that I can use it there as follows:
package mypack;
#Path("/MyService")
public class MyServiceClass {
//May be some annotation has to be given here which I don't know
HeaderClass header;
public void useHeader() {
//Code to use the header
System.out.println(header.getUserAgent());
}
}
I have the following inside beans.xml file
<jaxrs:server id="SampleService" address="/">
<jaxrs:features>
<cxf:logging />
</jaxrs:features>
<jaxrs:serviceBeans>
<ref bean="MyServiceClass"/>
</jaxrs:serviceBeans>
</jaxrs:server>
<bean id="MyServiceClass" class="mypack.MyServiceClass"/>
I don't know how to add the property HeaderClass in the bean "MyServiceClass"
I am using apache cxf with spring configuration file (beans.xml).
Please help.
One way to achieve this is to add those lines to your beans.xml:
<bean id="HeaderClass" class="mypack.HeaderClass"/>
<bean id="MyServiceClass" class="mypack.MyServiceClass">
<property name="header" ref="HeaderClass" />
</bean>
You may also need to add a setHeader() method to your MyServiceClass.