Is there an equivalent of EndpointInterceptorAdapter for the client?
Because i need to intercept outgoing and incoming messages from the client and do some work with them.
EndpointInterceptorAdapter intercepts only endpoint messages.
I think you can use the SmartEndpointInterceptor
public class SmartEndpointInterceptorImpl implements
SmartEndpointInterceptor
{
public boolean handleRequest(MessageContext messageContext, Object endpoint)
throws Exception
{
SaajSoapMessage soapSaajMsg = (SaajSoapMessage)messageContext.getRequest();
return true;
}
public boolean handleResponse(MessageContext messageContext, Object endpoint)
throws Exception {
return true;
}
//I omitted two more methods
}
Well, i found the answer.
You have to create a class that implements ClientInterceptor.
i.e.
package com.coral.project.interceptor;
public class WebServiceClientInterceptor implements ClientInterceptor {
#Override
public boolean handleRequest(MessageContext messageContext)
throws WebServiceClientException {
// TODO Auto-generated method stub
return true;
}
#Override
public boolean handleResponse(MessageContext messageContext)
throws WebServiceClientException {
// TODO Auto-generated method stub
return true;
}
#Override
public boolean handleFault(MessageContext messageContext)
throws WebServiceClientException {
// TODO Auto-generated method stub
return false;
}
}
and define in spring-ws config file:
<bean id="crmClient" class="com.coral.project.clients.CrmClient">
<property name="defaultUri" value="..."/>
<property name="marshaller" ref="jaxb2Marshaller" />
<property name="unmarshaller" ref="jaxb2Marshaller" />
<property name="interceptors">
<list>
<bean class="com.coral.project.interceptor.WebServiceClientInterceptor" />
</list>
</property>
</bean>
and that's it.
Related
I have an older Java application that I'm deploying to newer JBoss servers with Tomcat 8/Java 8 (up from Tomcat 7 and Java 7). I'm having some JNDI issues after deploying to the new servers. I'll get the error:
javax.naming.OperationNotSupportedException: Context is read only
Currently, I have a pooled datasource bean being created and then another bean that configures the JNDI reference.
<bean id="dataSourceBean" class="oracle.ucp.jdbc.PoolDataSourceFactory" factory-method="getPoolDataSource" >
<property name="URL" value="${URL}"/>
<property name="user" value="${user}"/>
<property name="password" value="${password}"/>
<property name="connectionFactoryClassName" value="${connectionFactoryClassName}"/>
<property name="minPoolSize" value="${minPoolSize}"/>
<property name="maxPoolSize" value="${maxPoolSize}"/>
<property name="validateConnectionOnBorrow" value="true"/>
<property name="inactiveConnectionTimeout" value="${inactiveConnectionTimeout}"></property>
<property name="fastConnectionFailoverEnabled" value="true"></property>
<property name="maxStatements" value="${maxStatements}"></property>
<property name="loginTimeout" value="${loginTimeout}"></property>
<property name="timeToLiveConnectionTimeout" value="${timeToLiveConnectionTimeout}"></property>
<property name="initialPoolSize" value="${initialPoolSize}"></property>
</bean>
<bean id="jndiConfiger" class="com.uprr.app.cam.common.util.DataBaseJndiConfig">
<property name="jndiName" value="java:comp/env/jdbc/com.uprr.app.cam.cam1_admin_Pool1TXDS"></property>
<property name="dataSource" ref="dataSourceBean"></property>
</bean>
And then the java class to configure it:
public class DataBaseJndiConfig implements InitializingBean {
private static final Logger log = Logger.getLogger(DataBaseJndiConfig.class);
private static boolean hasRun = false;
private String jndiName;
private DataSource dataSource;
private InitialContext ic;
public String getJndiName() {
return jndiName;
}
public void setJndiName(String jndiName) {
this.jndiName = jndiName;
}
public DataSource getDataSource() {
return dataSource;
}
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
}
public DataBaseJndiConfig(){
try {
log.error("IN JNDI CONFIG");
if(hasRun==false){
ic= new InitialContext();
ic.createSubcontext("java:comp");
ic.createSubcontext("java:comp/env");
ic.createSubcontext("java:comp/env/jdbc");
}
} catch (Exception e) {
log.error("Exception in the constructor of DataBaseJndiConfig :"+e);
}
}
public void afterPropertiesSet() {
try {
log.error("SETTING JNDI PROPERTIES");
if(hasRun==false){
if (dataSource != null && jndiName != null) {
ic.bind(jndiName, dataSource);
hasRun=true;
}
}
} catch (Exception e) {
log.error("Exception in the afterPropertiesSet of DataBaseJndiConfig :"+e);
}
}
}
The error comes when I first try and do a createSubcontext()
I've read some other threads that mention having a context.xml file with a tag but am having trouble deciphering what should do in that tag
Is it basically the "dataSourceBean" that would be converted to a tag? Then I'm guessing I could eliminate the "jndiConfiger" bean and should just be able do the JNDI reference without doing all that binding?
I have a similar question here
Guice with multiple concretes......picking one of them
with a solution for Guice.
But I have a different project using spring di (beans), but with the same kind of issue.
I have an interface with N number of concretes. (3 here)
public interface OrderProcessorInterface {
void ProcessOrder(String preferredShipperAbbreviation, Order ord);
}
public class FedExShipper implements ShipperInterface {
private Log logger;
public FedExShipper(Log lgr) {
if (null == lgr) {
throw new IllegalArgumentException("Log is null");
}
this.logger = lgr;
}
public void ShipOrder(Order ord) {
this.logger.info("I'm shipping the Order with FexEx");
}
}
public class UpsShipper implements ShipperInterface {
private Log logger;
public UpsShipper(Log lgr) {
if (null == lgr) {
throw new IllegalArgumentException("Log is null");
}
this.logger = lgr;
}
public void ShipOrder(Order ord) {
this.logger.info("I'm shipping the Order with Ups");
}
}
public class UspsShipper implements ShipperInterface {
private Log logger;
public UspsShipper(Log lgr) {
if (null == lgr) {
throw new IllegalArgumentException("Log is null");
}
this.logger = lgr;
}
public void ShipOrder(Order ord) {
this.logger.info("I'm shipping the Order with Usps");
}
}
........
Then I have a class that needs to know about ALL THREE concretes.
import java.util.Collection;
import java.util.Set;
import org.apache.commons.logging.Log;
public class OrderProcessorImpl implements OrderProcessorInterface {
private Log logger;
private java.util.Map<String, javax.inject.Provider<ShipperInterface>> shipperProviderMap;
public OrderProcessorImpl(Log lgr, java.util.Map<String, javax.inject.Provider<ShipperInterface>> spMap) {
if (null == lgr) {
throw new IllegalArgumentException("Log is null");
}
if (null == spMap) {
throw new IllegalArgumentException("Provider<ShipperInterface> is null");
}
this.logger = lgr;
this.shipperProviderMap = spMap;
}
public void ProcessOrder(String preferredShipperAbbreviation, Order ord) {
this.logger.info(String.format("About to ship. (%1s)", preferredShipperAbbreviation));
ShipperInterface foundShipperInterface = this.FindShipperInterface(preferredShipperAbbreviation);
foundShipperInterface.ShipOrder(ord);
}
private ShipperInterface FindShipperInterface(String preferredShipperAbbreviation) {
ShipperInterface foundShipperInterface = this.shipperProviderMap.get(preferredShipperAbbreviation).get();
if (null == foundShipperInterface) {
throw new NullPointerException(
String.format("ShipperInterface not found in shipperProviderMap. ('%1s')", preferredShipperAbbreviation));
}
return foundShipperInterface;
}
}
=============
Basically, I want to call the method, pass in a string argument, and have it choose the concrete for me. (if my real code, this is via a database value, but for the demo code, this is good enough)
Order ord = new Order();
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
BeanFactory factory = context;
OrderProcessorInterface opi = context.getBean(OrderProcessorImpl.class);
opi.ProcessOrder("myFedExName", ord); /* friendlyName would be nice, but fully qualified concrete name also assceptable */
My Spring Configuration is via xml:
<bean id="theLoggerBean"
class="org.apache.commons.logging.impl.Log4JLogger">
<constructor-arg value="log" />
</bean>
<bean id="fedExBean"
class="com.me.FedExShipper">
<constructor-arg ref="theLoggerBean"></constructor-arg>
</bean>
<bean id="uspsExBean"
class="com.me.FedExShipper">
<constructor-arg ref="theLoggerBean"></constructor-arg>
</bean>
<bean id="upsExBean"
class="com.me.FedExShipper">
<constructor-arg ref="theLoggerBean"></constructor-arg>
</bean>
..........
================================
<bean id="OrderProcessorImplBean"
class="com.me.OrderProcessorImpl">
<constructor-arg ref="theLoggerBean"></constructor-arg>
<constructor-arg ref="How do I do N Number of ShipperInterfaces Here ??"></constructor-arg>
</bean>
So I want to xml configure the 3 concretes.
And then inject them into the class.
But where I have "How do I do N Number of ShipperInterfaces Here ??", I have no idea what to do.
JSR 330 implementation preferred, but will take anything.
THANKS
Note, in the other question (the Guice one), this was also a possiblity for the constructor of the OrderProcessor:
public class OrderProcessorImpl implements OrderProcessorInterface {
private Log logger;
Set<ShipperInterface> shippers;
public OrderProcessorImpl(Log lgr, Set<ShipperInterface> shprs) {
if (null == lgr) {
throw new IllegalArgumentException("Log is null");
}
if (null == shprs) {
throw new IllegalArgumentException("ShipperInterface(s) is null");
}
this.logger = lgr;
this.shippers = shprs;
}
public void ProcessOrder(String preferredShipperAbbreviation, Order ord) {
this.logger.info(String.format("About to ship. (%1s)", preferredShipperAbbreviation));
for (ShipperInterface sh : shippers) {
this.logger.info(String.format("ShipperInterface . (%1s)", sh.getClass().getSimpleName()));
}
}
}
Something like this should work. This uses #Autowired and not xml configuration:
#org.springframework.stereotype.Service
public class OrderProcessorImpl implements OrderProcessorInterface {
private List<ShipperInterface> shipperProviders;
private Map<String, ShipperInterface> shipperProvidersMap = new HashMap<>();
#Autowired
public void setShipperProviders(List<ShipperInterface> shipperProviders) {
this.shipperProviders= shipperProviders;
this.shipperProviders.stream().forEach(p->shipperProvidersMap .put(/* your code for getting the key */, p));
}
Gradle dependency hint:
compile group: 'org.springframework', name: 'spring-context', version: '5.1.9.RELEASE'
I think I have something that works:
beans.xml (note the "util" extras in the namespace declares)
<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"
xmlns:util="http://www.springframework.org/schema/util"
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
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util-2.5.xsd">
<bean id="theLoggerBean"
class="org.apache.commons.logging.impl.Log4JLogger">
<constructor-arg value="log" />
</bean>
<bean id="fedExShipperBean"
class="com.me.shipping.FedExShipper">
<constructor-arg ref="theLoggerBean"></constructor-arg>
</bean>
<bean id="upsShipperBean"
class="com.me.shipping.UpsShipper">
<constructor-arg ref="theLoggerBean"></constructor-arg>
</bean>
<bean id="uspsShipperBean"
class="com.me.shipping.UspsShipper">
<constructor-arg ref="theLoggerBean"></constructor-arg>
</bean>
<util:map id="shipperInterfaceMap" key-type="java.lang.String"
value-type="com.me.shipping.interfaces.ShipperInterface">
<entry key="fedexFriendlyName" value-ref="fedExShipperBean" />
<entry key="upsFriendlyName" value-ref="upsShipperBean" />
<entry key="uspsFriendlyName" value-ref="uspsShipperBean" />
</util:map>
<bean id="orderProcessorImplBean"
class="com.me.shipping.OrderProcessorImpl">
<constructor-arg ref="theLoggerBean"></constructor-arg>
<constructor-arg ref="shipperInterfaceMap"></constructor-arg>
</bean>
</beans>
and java
package com.me.shipping;
import java.util.Collection;
import java.util.Map;
import java.util.Set;
import org.apache.commons.logging.Log;
import com.me.shipping.interfaces.OrderProcessorInterface;
import com.me.shipping.interfaces.ShipperInterface;
import com.me.Models.Order;
public class OrderProcessorImpl implements OrderProcessorInterface {
private Log logger;
private java.util.Map<String, ShipperInterface> shipperInterfaceMap;
public OrderProcessorImpl(Log lgr, java.util.Map<String, ShipperInterface> siMap) {
if (null == lgr) {
throw new IllegalArgumentException("Log is null");
}
if (null == siMap) {
throw new IllegalArgumentException("Map<String, ShipperInterface> is null");
}
this.logger = lgr;
this.shipperInterfaceMap = siMap;
}
public void ProcessOrder(String preferredShipperAbbreviation, Order ord) {
this.logger.info(String.format("About to ship. (%1s)", preferredShipperAbbreviation));
ShipperInterface foundShipperInterface = this.FindShipperInterface(preferredShipperAbbreviation);
foundShipperInterface.ShipOrder(ord);
}
private ShipperInterface FindShipperInterface(String friendlyName)
{
ShipperInterface returnItem = null;
if (null != this.shipperInterfaceMap)
{
returnItem = this.shipperInterfaceMap.entrySet().stream()
.filter(e -> e.getKey().equalsIgnoreCase(friendlyName))
.map(Map.Entry::getValue)
.findFirst()
.orElse(null);
}
if (null == returnItem)
{
throw new NullPointerException(String.format("shipperProviderMap did not contain expected item. (Key='%s')", friendlyName));
}
return returnItem;
}
}
and "main" method
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
BeanFactory factory = context;
Order ord = new Order();
OrderProcessorInterface opi = context.getBean(OrderProcessorImpl.class);
opi.ProcessOrder("fedexFriendlyName", ord);
<!-- Total Customer service dao facade-->
<bean id="totalCustomersDao"
class="de.hybris.training.core.dao.impl.TotalCustomersDaoImpl">
<property name="flexibleSearchService" ref="flexibleSearchService"/>
</bean>
<bean id="totalCustomerService" class=" de.hybris.training.core.impl.TotalCustomerServiceImpl">
<property name="totalCustomersDao" ref="totalCustomersDao"/>
</bean>
<bean id="totalCustomerFacade" class="de.hybris.training.core.facade.impl.TotalCustomerFacadeImpl">
<property name="totalCustomerService" ref="totalCustomerService"/>
</bean>
<bean id="usersFindJob" class=" de.hybris.training.core.job.UsersFindJob"
parent="abstractJobPerformable" >
</bean>
this is xml.
This is facade class
public class TotalCustomerFacadeImpl implements TotalCustomerFacade {
//TODO autowired or resoucre not work
private TotalCustomerService totalCustomerService ;
private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(UsersFindJob.class);
public TotalCustomerService getTotalCustomerService() {
return totalCustomerService;
}
public void setTotalCustomerService(TotalCustomerService totalCustomerService) {
this.totalCustomerService = totalCustomerService;
}
here for
private TotalCustomerService totalCustomerService ;
when i put autorwired, it says
could not autowire no beans of type found
WHen i write resource or resource(name=totalCustomerService)
it gives null pointer.
this is serviceimpl
public class TotalCustomerServiceImpl implements TotalCustomerService {
private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(UsersFindJob.class);
#Autowired
private TotalCustomersDao totalCustomersDao;
public TotalCustomersDao getTotalCustomersDao() {
return totalCustomersDao;
}
public void setTotalCustomersDao(TotalCustomersDao totalCustomersDao) {
this.totalCustomersDao = totalCustomersDao;
} public List<CustomerModel> getAllCustomersNames (String name) { LOG.info("***********************************");
LOG.info("***********************************");
LOG.info("*************************getAllCustomersNames::");
LOG.info("***********************************");
LOG.info("***********************************");
List<CustomerModel> customerModels = totalCustomersDao.findAllCustomersFromDao( name);
return customerModels;
}
those are interfaces
public interface TotalCustomerService {
List<CustomerModel> getAllCustomersNames (String name);
}
public interface TotalCustomerFacade {
List<String> findCustomerContainingName(String firstName);
}
how can i solve this?
the paths are they are all in
de.hybris.training.core
divided like
dao
facade
service
what can i do? I need to go for that service. I tried lots of times. added autowired. removed , let it without any annotations but still same.
Also this did not work
#Autowired
#Qualifier("totalCustomerService")
private TotalCustomerService totalCustomerService ;
remove whitespace! class=" de.hybris.training
Change
<bean id="totalCustomerService" class=" de.hybris.training.core.impl.TotalCustomerServiceImpl">
to
<bean id="totalCustomerService" class="de.hybris.training.core.impl.TotalCustomerServiceImpl">
it is because of whitespace
class=" de.
here
I have something like this...
class DomainConverter implements GenericConverter {
private Class<Domain> classOfDomain;
private Class<DomainCommand> classOfDomainCommand;
public Set<GenericConverter.ConvertiblePair> getConvertibleTypes() {
Set<GenericConverter.ConvertiblePair> convertiblePairs = new HashSet<GenericConverter.ConvertiblePair>();
convertiblePairs.add(new GenericConverter.ConvertiblePair(classOfDomain, classOfDomainCommand));
convertiblePairs.add(new GenericConverter.ConvertiblePair(classOfDomainCommand, classOfDomain));
return convertiblePairs;
}
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
if (classOfDomain.equals(sourceType.getType())) {
return this.convert((Domain) source);
} else {
return this.convertBack((DomainCommand) source);
}
}
protected DomainCommand convert(Domain definition){
...
}
protected Domain convertBack(DomainCommand command){
...
}
}
Do I have to wire it within the class or add it to the resources.groovy?
How do I create the DomainCommand so that I still have my autowiring
Looking at the Spring documentation you can see an example of bean declaration:
<bean id="conversionService"
class="org.springframework.context.support.ConversionServiceFactoryBean"/>
<bean id="conversionService"
class="org.springframework.context.support.ConversionServiceFactoryBean">
<property name="converters">
<list>
<bean class="example.MyCustomConverter"/>
</list>
</property>
</bean>
So you need to declare your converter and also the conversionService in your resources.groovy file.
In my restful webservice, in case of bad request (5xx) or 4xx respose codes, I write a custom header "x-app-err-id" to the response.
On the client side, I use exchange method of RestTemplate to make a RestFul web service call. Everything is fine when the response code is 2xx.
ResponseEntity<Component> response = restTemplate.exchange(webSvcURL,
HttpMethod.POST,
requestEntity,
Component.class);
But if there is an exception(HttpStatusCodeException) because of it being a bad request(5xx) or 4xx, in the catch block of HttpStatusCodeException, I get response(see above) as null and so I do not have access to my custom header I set in my web service. How do I get custom headers from the response in case of exceptions in RestTemplate.
One more question is, I set an error object(json) in the reponse body in case of error and I would like to know how to access response body as well in case of exceptions in RestTemplate
I finally did it using ResponseErrorHandler.
public class CustomResponseErrorHandler implements ResponseErrorHandler {
private static ILogger logger = Logger.getLogger(CustomResponseErrorHandler.class);
private ResponseErrorHandler errorHandler = new DefaultResponseErrorHandler();
public void handleError(ClientHttpResponse response) throws IOException {
List<String> customHeader = response.getHeaders().get("x-app-err-id");
String svcErrorMessageID = "";
if (customHeader != null) {
svcErrorMessageID = customHeader.get(0);
}
try {
errorHandler.handleError(response);
} catch (RestClientException scx) {
throw new CustomException(scx.getMessage(), scx, svcErrorMessageID);
}
}
public boolean hasError(ClientHttpResponse response) throws IOException {
return errorHandler.hasError(response);
}
}
And then use this custom response handler for RestTemplate by configuring as shown below
<bean id="restTemplate" class="org.springframework.web.client.RestTemplate">
<property name="messageConverters">
<list>
<ref bean="jsonConverter" />
</list>
</property>
<property name="errorHandler" ref="customErrorHandler" />
</bean>
<bean id="jsonConverter" class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter">
<property name="supportedMediaTypes" value="application/json" />
</bean>
<bean id="customErrorHandler " class="my.package.CustomResponseErrorHandler">
</bean>
You shouldn't have to create a custom error handler. You can get the body and headers from the HttpStatusCodeException that gets thrown.
try {
ResponseEntity<Component> response = restTemplate.exchange(webSvcURL,
HttpMethod.POST,
requestEntity,
Component.class);
} catch (HttpStatusCodeException e) {
List<String> customHeader = e.getResponseHeaders().get("x-app-err-id");
String svcErrorMessageID = "";
if (customHeader != null) {
svcErrorMessageID = customHeader.get(0);
}
throw new CustomException(e.getMessage(), e, svcErrorMessageID);
// You can get the body too but you will have to deserialize it yourself
// e.getResponseBodyAsByteArray()
// e.getResponseBodyAsString()
}
If you use a global exception handler add the below method or check this
https://www.javaguides.net/2018/09/spring-boot-2-exception-handling-for-rest-apis.html add below method in GlobalExceptionHandler class
#ExceptionHandler({HttpClientErrorException.class, HttpStatusCodeException.class, HttpServerErrorException.class})
#ResponseBody
public ResponseEntity<Object> httpClientErrorException(HttpStatusCodeException e) throws IOException {
BodyBuilder bodyBuilder = ResponseEntity.status(e.getRawStatusCode()).header("X-Backend-Status", String.valueOf(e.getRawStatusCode()));
if (e.getResponseHeaders().getContentType() != null) {
bodyBuilder.contentType(e.getResponseHeaders().getContentType());
}
return bodyBuilder.body(e.getResponseBodyAsString());
}