I want to send data from Boot(Server) to client!
I am using stomp websocket!
WebSocketClient doesn't work with error that the HTTP response from the server [200] did not permit the HTTP upgrade to WebSocket!
It's my Java Stomp WebSocket client code!
In this code, I tried to config handShakeHeader.... but it doesn't work!
package refill.station.websocket;
import org.junit.jupiter.api.Test;
import org.springframework.messaging.converter.MappingJackson2MessageConverter;
import org.springframework.messaging.simp.stomp.StompHeaders;
import org.springframework.messaging.simp.stomp.StompSession;
import org.springframework.messaging.simp.stomp.StompSessionHandler;
import org.springframework.messaging.simp.stomp.StompSessionHandlerAdapter;
import org.springframework.scheduling.concurrent.ConcurrentTaskScheduler;
import org.springframework.web.socket.WebSocketHttpHeaders;
import org.springframework.web.socket.client.WebSocketClient;
import org.springframework.web.socket.client.standard.StandardWebSocketClient;
import org.springframework.web.socket.messaging.WebSocketStompClient;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutionException;
public class WebSocketTest {
#Test
public void WebSocketTest() {
WebSocketClient webSocketClient = new StandardWebSocketClient();
WebSocketStompClient stompClient = new WebSocketStompClient(webSocketClient);
stompClient.setMessageConverter(new MappingJackson2MessageConverter());
stompClient.setTaskScheduler(new ConcurrentTaskScheduler());
String url = "ws://localhost:8080/ws/websocket";
StompSessionHandler sessionHandler = new StompSessionHandlerAdapter() {};
List<String> protocols = new ArrayList<>();
protocols.add("v10.stomp");
protocols.add("v11.stomp");
WebSocketHttpHeaders handSahkeHeaders = new WebSocketHttpHeaders();
handSahkeHeaders.setUpgrade("websocket");
handSahkeHeaders.setConnection("Upgrade");
handSahkeHeaders.setSecWebSocketVersion("13");
handSahkeHeaders.setSecWebSocketKey("4hb9p5/JjeKLed5aXlBqnw==");
handSahkeHeaders.setSecWebSocketProtocol(protocols);
StompHeaders stompHeaders = new StompHeaders();
StompSession stompSession = null;
try {
stompSession = stompClient.connect(URI.create(url), handSahkeHeaders, stompHeaders, sessionHandler).get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
stompSession.send("/app/control/complete", "msg");
// StompSession stompSession = stompClient.connect(url, sessionHandler).get();
}
}
I checked my WebSocket server with javascript and it works correctly!
This is my WebSocket server configuration!
package refill.station.config.websocket;
import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer;
import org.springframework.web.socket.server.RequestUpgradeStrategy;
import org.springframework.web.socket.server.standard.TomcatRequestUpgradeStrategy;
import org.springframework.web.socket.server.support.DefaultHandshakeHandler;
#Configuration
#EnableWebSocketMessageBroker
public class WebSocketConfiguration implements WebSocketMessageBrokerConfigurer {
#Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
RequestUpgradeStrategy upgradeStrategy = new TomcatRequestUpgradeStrategy();
registry.addEndpoint("/ws")
.withSockJS();
registry.addEndpoint("/ws")
.setHandshakeHandler(new DefaultHandshakeHandler(upgradeStrategy))
.setAllowedOrigins("*");
}
#Override
public void configureMessageBroker(MessageBrokerRegistry registry) {
registry.setApplicationDestinationPrefixes("/app");
registry.enableSimpleBroker("/control");
}
}
last, it's my controller for websocket!
package refill.station.controller.websocket;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.messaging.handler.annotation.Payload;
import org.springframework.messaging.handler.annotation.SendTo;
import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
#RequiredArgsConstructor
#RestController
#Slf4j
public class RefillerCommunicateController {
#MessageMapping("/control/complete")
#SendTo("/control/operate")
public String test(#Payload String data) {
log.info("RefillerCommunicateController-test method");
return "test";
}
}
Related
I am unable to moock webclient
WebClientConfig.java
public #Bean("oauthWebClient") WebClient oauthWebClient() {
return WebClient.builder()
.clientConnector(new ReactorClientHttpConnector(
HttpClient.create().option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 1000)
.doOnConnected(connection -> connection.addHandlerLast(new ReadTimeoutHandler(10))
.addHandlerLast(new WriteTimeoutHandler(10)))))
.filter(logOAuthResponse()).baseUrl(oauthTokenUrl)
.defaultHeaders(headers -> {
headers.setBasicAuth(secretHeaderValue);
headers.add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_FORM_URLENCODED_VALUE);
})
.defaultUriVariables(oauthUriVariables)
.build();
}
serviceUti.java
package com.test.stats.volts.busops.utils;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.retry.annotation.Recover;
import org.springframework.retry.annotation.Retryable;
import org.springframework.stereotype.Component;
import org.springframework.web.reactive.function.client.WebClient;
import org.springframework.web.reactive.function.client.WebClientRequestException;
import org.springframework.web.reactive.function.client.WebClientResponseException;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.test.stats.volts.busops.exception.VoltsDataAccessException;
import com.test.stats.volts.busops.exception.MtnDataAccessNotRespondingException;
import com.test.stats.volts.busops.exception.VoltsDataAcessException;
import com.test.stats.volts.busops.exception.UnableToGetOAuthTokenException;
#Component("voltsDataAccessServiceUtil")
public class ServiceUtil {
private static final Logger logger = LoggerFactory.getLogger(ServiceUtil.class);
#Autowired
#Qualifier("voltsDataAccessWebClient")
WebClient voltsDataAccessClient;
#Autowired
#Qualifier("oauthWebClient")
WebClient oauthClient;
#Value("${volts.dataaccess.end.point.save-meeting}")
private String saveMeetingEndPoint;
#Value("${volts.dataaccess.oauth.header-key.name}")
private String oauthHeaderKeyName;
#Value("${volts.dataccess.oauth.response.token.key-name}")
private String oauthResponseTokenKeyName;
#Value("#{${volts.dataaccess.api.endpoints.default.uri-variables}}")
private Map<String, String> voltsDataAccessUriVariables;
#Autowired
ObjectMapper mapper;
#Value("#{${volts.dataaccess.oauth.uri-variables}}")
private Map<String, String> oauthUriVariables;
#Value("${volts.dataaccess.oauth.scope}")
private String oauthScope;
#Value("${volts.dataaccess.oauth.grant_type}")
private String grantType;
#Value("${volts.dataaccess.oauth.secret.header-name}")
private String secretHeaderName;
#Value("${volts.dataaccess.oauth.secret.header-value}")
private String secretHeaderValue;
#Value("${volts.dataaccess.end.point.fetch-meeting}")
private String fetchMeetingEndPoint;
#Value("${volts.dataaccess.query.param.api-key-value}")
private String apiKey;
#Retryable(maxAttempts = 2)
public String postOAuthToken() throws VoltsDataAccessException {
try {
String respEntity = oauthClient.post()
.uri(uriBuilder -> uriBuilder.queryParam("scope", oauthScope).queryParam("grant_type", grantType)
.build())
.headers(headers -> headers.setBasicAuth(secretHeaderValue))
.retrieve()
.bodyToMono(String.class)
.block();
if (respEntity == null)
throw new UnableToGetOAuthTokenException(
"Exception while fetching OAUthToken as response from OAUth service is null resposne body");
try {
return mapper.readValue(respEntity, ObjectNode.class).get(oauthResponseTokenKeyName).asText();
} catch (JsonProcessingException e) {
logger.error("Exception while pasring token from Oauth ", e);
throw new UnableToGetOAuthTokenException(
"Exception while fetching OAUthToken as response from OAUth service is null resposne body");
}
} catch (WebClientRequestException e) {
logger.error("Request Exception to OAUth: message {}", e.getMessage(), e);
logger.error("", e);
throw new VoltsDataAccessException(e.getMessage(), HttpStatus.REQUEST_TIMEOUT.value());
}
catch (WebClientResponseException e) {
throw new VoltsDataAccessException(e.getMessage(), e.getRawStatusCode());
}
}
#Retryable(value = VoltsDataAcessException.class)
public ResponseEntity<VoltsResp> postSaveMeetingDetails(SaveVoltsReq voltsReq)
throws VoltsDataAcessException {
try {
ResponseEntity<VoltsResp> resp = voltsDataAccessClient.post()
.uri(saveMeetingEndPoint, uri -> uri.queryParam("apikey", apiKey).build())
.headers(headers -> headers.setBearerAuth(postOAuthToken()))
.contentType(MediaType.APPLICATION_JSON).bodyValue(voltsReq).retrieve()
.toEntity(VoltsResp.class).block();
return resp;
} catch (WebClientRequestException e) {
throw new VoltsDataAcessException(e.getMessage(), HttpStatus.REQUEST_TIMEOUT.value());
} catch (WebClientResponseException e) {
throw new VoltsDataAcessException(e.getMessage(), e.getRawStatusCode());
}
}
}
My test classs
WebClienrTests.java
import static org.assertj.core.api.Assertions.assertThat;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.web.reactive.function.client.WebClient;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.test.stats.volts.busops.config.WebClientConfig;
import com.test.stats.volts.busops.utils.ServiceUtil;
import okhttp3.mockwebserver.MockResponse;
import okhttp3.mockwebserver.MockWebServer;
#SpringBootTest(classes = { ServiceUtil.class, WebClientConfig.class,
ObjectMapper.class })
#RunWith(SpringRunner.class)
class ServiceUtilTests {
public static MockWebServer mockServer = new MockWebServer();
#MockBean
WebClientConfig webClientCondfig;
#Autowired
ServiceUtil serviceUtil;
#MockBean(name = "oauthWebClient")
WebClient oauthClient;
#MockBean(name = "voltsDataAccessWebClient")
WebClient voltsDataAccessWebClient;
#BeforeEach
void startMockServer() throws Exception {
mockServer.start(9090);
oauthClient = WebClient.create(mockServer.url("/").url().toString());
}
#AfterEach
void stopMockServer() throws Exception {
mockServer.shutdown();
}
#Test
void testPostOAuth() throws Exception {
mockServer.enqueue(new MockResponse().setResponseCode(200).setBody("OAuthToken"));
String expected = serviceUtil.postOAuthToken();
assertThat(expected).isNotNull().isEqualTo("OAuthToken");
}
}
When I run above test I get this error
java.lang.NullPointerException:
At postAuthToken() while setting headers .headers(headers -> headers.setBasicAuth(secretHeaderValue))
Please help on how to mock whole thing
I created one spring boot app. I need to upload any file(doc,pdf,mp3 etc..) on sftp server. when user upload file my spring app can able to create url and save file details(on which server file is located, download url of file, who is the own of that file etc..) to h2 database.
and when user ask for file.. spring boot can able to fetch file details form database.. and display that file on browser. and user can also able to download that file. can any one help..enter image description here
Java Configuration
import com.example.springintegrationhttp.FilePrinter;
import org.springframework.context.annotation.Bean;
import org.springframework.expression.common.LiteralExpression;
import org.springframework.integration.annotation.InboundChannelAdapter;
import org.springframework.integration.annotation.ServiceActivator;
import org.springframework.integration.core.MessageSource;
import org.springframework.integration.file.FileNameGenerator;
import org.springframework.integration.file.filters.AcceptOnceFileListFilter;
import org.springframework.integration.sftp.filters.SftpSimplePatternFileListFilter;
import org.springframework.integration.sftp.inbound.SftpInboundFileSynchronizer;
import org.springframework.integration.sftp.inbound.SftpInboundFileSynchronizingMessageSource;
import org.springframework.integration.sftp.outbound.SftpMessageHandler;
import org.springframework.integration.sftp.session.DefaultSftpSessionFactory;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageHandler;
import org.springframework.stereotype.Component;
import java.io.File;
#org.springframework.context.annotation.Configuration
#Component
public class Configuration {
#Bean
public DefaultSftpSessionFactory sftpSessionFactory(){
DefaultSftpSessionFactory defaultSftpSessionFactory = new DefaultSftpSessionFactory();
defaultSftpSessionFactory.setHost("0.0.0.0");
defaultSftpSessionFactory.setPort(22);
defaultSftpSessionFactory.setUser("abhishek");
defaultSftpSessionFactory.setPassword("12345");
defaultSftpSessionFactory.setAllowUnknownKeys(true);
System.out.println("Value in SftpSession: " + defaultSftpSessionFactory);
return defaultSftpSessionFactory;
}
#Bean
#ServiceActivator(inputChannel = "tosftpChannel")
public MessageHandler handler(){
SftpMessageHandler messageHandler = new SftpMessageHandler(sftpSessionFactory());
messageHandler.setRemoteDirectoryExpression(new LiteralExpression("upload"));
messageHandler.setFileNameGenerator(new FileNameGenerator() {
#Override
public String generateFileName(Message<?> message) {
System.out.println(message.getHeaders().get("fileName"));
System.out.println(message.getPayload());
return message.getHeaders().get("fileName").toString();
}
});
return messageHandler;
}
#Bean
public SftpInboundFileSynchronizer sftpInboundFileSynchronizer(){
SftpInboundFileSynchronizer fileSynchronizer = new SftpInboundFileSynchronizer(sftpSessionFactory());
fileSynchronizer.setDeleteRemoteFiles(false);
fileSynchronizer.setRemoteDirectory("upload");
System.out.println("M a gaya");
fileSynchronizer.setFilter(new SftpSimplePatternFileListFilter("*.txt"));
return fileSynchronizer;
}
#Bean
//#InboundChannelAdapter(channel = "sftpChannel", poller = #Poller(fixedDelay = "5000"))//,autoStartup = "false")
#InboundChannelAdapter(channel = "sftpChannel")//,autoStartup = "false")
public MessageSource<File> sftpMessageSource(){
System.out.println("Into sftpMessageSource()");
SftpInboundFileSynchronizingMessageSource source = new SftpInboundFileSynchronizingMessageSource(sftpInboundFileSynchronizer());
source.setLocalDirectory(new File("target/foo"));
source.setAutoCreateLocalDirectory(true);
System.out.println("Flow");
source.setLocalFilter(new AcceptOnceFileListFilter<File>());
source.setMaxFetchSize(1);
//sftpInboundFileSynchronizer();
return source;
}
/*OutBoundGateway*/
/* #Bean
#ServiceActivator(inputChannel = "sftpChannel",)
public MessageHandler handler(){
SftpOutboundGateway outboundGateway = new SftpOutboundGateway(sftpSessionFactory(),
"get","payload");
outboundGateway.setLocalDirectory(new File("target/gatewayhand"));
outboundGateway.setAutoCreateLocalDirectory(true);
return outboundGateway;
}*/
/*OutBoundGateway*/
#Bean
#ServiceActivator(inputChannel = "sftpChannel")
public MessageHandler DownloadHandler(){
//return new SftpOutboundGateway(sftpSessionFactory(),"ls");
return message -> {
System.out.println("In Service Activator: " + message.getPayload());
File f = (File) message.getPayload();
FilePrinter f2 = new FilePrinter();
f2.print(f);
System.out.println(f.getName());
//sftpMessageSource();
//p.print(File file);
};
}
}
Gateway
import org.springframework.integration.annotation.Gateway;
import org.springframework.integration.annotation.MessagingGateway;
import org.springframework.messaging.handler.annotation.Header;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.io.InputStream;
#Component
#MessagingGateway
public interface UplaodGateway {
#Gateway(requestChannel = "tosftpChannel")
public void sendToSftp(#Header("fileName") String fileName, InputStream file);
/* #Gateway(requestChannel = "sftpChannel")
public void read(String fileName);*/
}
Controller
import com.example.springintegrationhttp.service.UploadService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import javax.websocket.server.PathParam;
import java.io.IOException;
#RestController
//#RequiredArgsConstructor
public class uplaodController {
#Autowired
UploadService uploadService;
#PostMapping("/upload")
public ResponseEntity<String> upladFile(#RequestParam("file")MultipartFile file) throws IOException {
return uploadService.uplaodToServer(file);
}
#GetMapping("/read")
public String readf(#PathParam("fileName")String fileName){
uploadService.readFileFromServer(fileName);
return "I want to fetch that file which user want";
}
}
//}
Thank You
I am trying to write a spring cloud stream processor class that takes an XML in through using the #StreamListener(Processor.INPUT) annotation.
The processor then extracts smaller XML messages and sends them to the output via this.processor.output().send(message);
I have not yet deployed this to dataflow because I wanted to test it with junit. When I run this with junit I can not seem to get my Processor object to instantiate.
I have tried using #Autowired which is how I have seen it done in may examples but I can't seem to get it to work. Any ideas would be appreciated.
My code is below.
package io.spring.dataflow.sample.usagecostprocessor;
import java.io.File;
import java.io.StringReader;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.List;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.stream.annotation.EnableBinding;
import org.springframework.cloud.stream.annotation.StreamListener;
import org.springframework.cloud.stream.messaging.Processor;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.stereotype.Component;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import lombok.AllArgsConstructor;
#AllArgsConstructor
#EnableBinding(Processor.class)
public class REDACTXMLSplitter {
private Processor processor;
//#Autowired
//private SendingBean sendingBean;
#SuppressWarnings("unchecked")
#StreamListener(Processor.INPUT)
public void parseForREDACTApplications(String redactXML) {
InputSource doc = new InputSource( new StringReader( redactXML ) );
try
{
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(true); // never forget this!
XPathFactory xfactory = XPathFactory.newInstance();
XPath xpath = xfactory.newXPath();
String xpathQuery = "//REDACT/Application";
xpath = xfactory.newXPath();
XPathExpression query = xpath.compile(xpathQuery);
NodeList productNodesFiltered = (NodeList) query.evaluate(doc, XPathConstants.NODESET);
for (int i=0; i<productNodesFiltered.getLength(); ++i)
{
Document suppXml = dBuilder.newDocument();
//we have to recreate the root node <products>
Element root = suppXml.createElement("REDACT");
Node productNode = productNodesFiltered.item(i);
//we append a product (cloned) to the new file
Node clonedNode = productNode.cloneNode(true);
suppXml.adoptNode(clonedNode); //We adopt the orphan :)
root.appendChild(clonedNode);
suppXml.appendChild(root);
//write out files
//At the end, we save the file XML on disk
// TransformerFactory transformerFactory = TransformerFactory.newInstance();
// Transformer transformer = transformerFactory.newTransformer();
// transformer.setOutputProperty(OutputKeys.INDENT, "yes");
// DOMSource source = new DOMSource(suppXml);
// StreamResult result = new StreamResult(new File("test_" + i + ".xml"));
// transformer.transform(source, result);
TransformerFactory tf = TransformerFactory.newInstance();
Transformer transformer = tf.newTransformer();
transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
StringWriter writer = new StringWriter();
transformer.transform(new DOMSource(suppXml), new StreamResult(writer));
String output = writer.getBuffer().toString().replaceAll("\n|\r", "");
System.out.println(output);
Message<String> message = (Message<String>) suppXml;
this.processor.output().send(message);
}
}
catch (XPathExpressionException | ParserConfigurationException | TransformerException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
package io.spring.dataflow.sample.usagecostprocessor;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
#SpringBootApplication
public class REDACTXMLSplitterApplication {
public static void main(String[] args) {
SpringApplication.run(REDACTXMLSplitterApplication.class, args);
}
}
package io.spring.dataflow.sample.usagecostprocessor;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.cloud.stream.messaging.Processor;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.util.ResourceUtils;
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
#RunWith(SpringRunner.class)
#SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
#DirtiesContext
public class MAIPXMLSplitterApplicationTests {
#Autowired
private Processor myProcessor;
#Test
public void contextLoads() {
}
#Test
public void parseXML() {
try {
String cmErrorPayloadXML = readFile(ResourceUtils.getFile(this.getClass().getResource("/XMLSamples/REDACTApplicationXMLSamples/redact.xml")));
REDACTXMLSplitter redactXMLSplitter = new REDACTXMLSplitter(myProcessor);
redactXMLSplitter.parseForREDACTApplications(cmErrorPayloadXML);
} catch (IOException e) {
e.printStackTrace();
}
}
public String readFile(File file) {
StringBuffer stringBuffer = new StringBuffer();
if (file.exists())
try {
//read data from file
FileInputStream fileInputStream = new FileInputStream(file);
int c;
while ((c = fileInputStream.read()) != -1){
stringBuffer.append((char) c);
}
} catch (IOException e) {
e.printStackTrace();
}
return stringBuffer.toString();
}
}
Update,
I tried this but myProcessor is still null
package io.spring.dataflow.sample.usagecostprocessor;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.cloud.stream.annotation.EnableBinding;
import org.springframework.cloud.stream.messaging.Processor;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.util.ResourceUtils;
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
#RunWith(SpringRunner.class)
#SpringBootTest(classes = MAIPXMLSplitterApplicationTests.TestProcessor.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class MAIPXMLSplitterApplicationTests {
#Autowired
private Processor myProcessor;
#Test
public void contextLoads() {
}
#Test
public void parseXML() {
try {
String cmErrorPayloadXML = readFile(ResourceUtils.getFile(this.getClass().getResource("/XMLSamples/MAIPApplicationXMLSamples/354_20191126_MAIP.xml")));
MAIPXMLSplitter maipXMLSplitter = new MAIPXMLSplitter(myProcessor);
maipXMLSplitter.parseForMAIPApplications(cmErrorPayloadXML);
} catch (IOException e) {
e.printStackTrace();
}
}
public String readFile(File file) {
StringBuffer stringBuffer = new StringBuffer();
if (file.exists())
try {
//read data from file
FileInputStream fileInputStream = new FileInputStream(file);
int c;
while ((c = fileInputStream.read()) != -1){
stringBuffer.append((char) c);
}
} catch (IOException e) {
e.printStackTrace();
}
return stringBuffer.toString();
}
#EnableBinding(Processor.class)
#EnableAutoConfiguration
public static class TestProcessor {
}
}
You need to have #EnableBinding(Processor.class) in one of the configuration classes used by the Test class.
Typically, you can have a simple #Configuration subclass and have it part of the #SpringBootTest classes list. You can see an example here
package org.springframework.webflux.websocket.webfluxwebsocketdemo;
import java.net.URISyntaxException;
import java.time.Duration;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.reactive.HandlerMapping;
import org.springframework.web.reactive.handler.SimpleUrlHandlerMapping;
import org.springframework.web.reactive.socket.WebSocketHandler;
import org.springframework.web.reactive.socket.server.support.WebSocketHandlerAdapter;
import reactor.core.publisher.Flux;
#SpringBootApplication
#RestController
public class WebFluxWebSocketDemoApplication {
public static void main(String[] args) {
SpringApplication.run(WebFluxWebSocketDemoApplication.class, args);
}
#GetMapping(path = "/pushData")
public void getRemoteStreaming( #RequestParam("message") String message ) throws URISyntaxException {
}
#Bean
public HandlerMapping webSocketMapping() {
Map<String, WebSocketHandler> map = new HashMap<>();
map.put("/echo", session -> session.send(
Flux.<String>generate(sink -> sink.next(String.format("{ message: 'got local message', date: '%s' }", new Date())))
.delayElements(Duration.ofSeconds(1)).map(session::textMessage)));
SimpleUrlHandlerMapping mapping = new SimpleUrlHandlerMapping();
mapping.setUrlMap(map);
mapping.setOrder(1);
return mapping;
}
#Bean
public WebSocketHandlerAdapter handlerAdapter() {
return new WebSocketHandlerAdapter();
}
}
Above code will send the message every second to websocket client
"{ message: 'got local message', date: 'Tue Oct 02 11:34:17 IST 2018' }"
But how do we send the message whenever i received the data from "pushData" resource, then i have to pass it to websocket client.
I am working on a Spring 4 web application and have run into a problem with #Async running synchronously. This is 100% annotation driven. No XML files.
App:
package com.kc2112.app;
import com.kc2112.app.controllers.MyStopWatch;
import javax.annotation.Resource;
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.task.TaskExecutor;
import org.springframework.scheduling.annotation.AsyncConfigurer;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
#EnableAsync
#EnableScheduling
#Configuration
public class WebApp extends AbstractAnnotationConfigDispatcherServletInitializer implements AsyncConfigurer {
#Resource
#Qualifier("stopwatch")
public MyStopWatch stopwatch;
public WebApp() {
super();
stopwatch = new MyStopWatch();
}
#Override
protected Class<?>[] getRootConfigClasses() {
return new Class<?>[0];
}
#Override
protected Class<?>[] getServletConfigClasses() {
return new Class<?>[]{AppConfig.class};
}
#Override
protected String[] getServletMappings() {
return new String[]{"/"};
}
#Override
public TaskExecutor getAsyncExecutor() {
ThreadPoolTaskExecutor te = new ThreadPoolTaskExecutor();
te.setMaxPoolSize(25);
te.setThreadNamePrefix("LULExecutor-");
te.initialize();
return te;
}
#Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return null;
}
}
Configuration:
package com.kc2112.app;
import com.kc2112.app.controllers.MySampleService;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
import org.springframework.web.servlet.view.JstlView;
import org.springframework.web.servlet.view.UrlBasedViewResolver;
#Configuration
#EnableAsync
#ComponentScan( basePackages = {"com"}, excludeFilters={
#ComponentScan.Filter(type=FilterType.ASSIGNABLE_TYPE, value=MySampleService.class)} )
public class AppConfig{
#Bean
public static PropertySourcesPlaceholderConfigurer properties() {
return new PropertySourcesPlaceholderConfigurer();
}
#Bean
public UrlBasedViewResolver urlBasedViewResolver()
{
UrlBasedViewResolver res = new InternalResourceViewResolver();
res.setViewClass(JstlView.class);
res.setPrefix("/WEB-INF/jsp/");
res.setSuffix(".jsp");
return res;
}
}
Controller:
package com.kc2112.app.controllers;
import java.util.ArrayList;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
#RestController
public class MyAsyncController {
#Autowired
MyStopWatch stopwatch;
public MySampleService mySampleService = new MySampleService();
#RequestMapping(value = "/go", produces = {MediaType.TEXT_HTML_VALUE}, method = RequestMethod.GET)
public String taskExecutor() throws InterruptedException, ExecutionException {
ArrayList<Future<Boolean>> asyncResults = new ArrayList();
for (int i = 0; i < 10; i++) {
asyncResults.add(mySampleService.callAsync(i));
}
return "time passed is " + stopwatch.getTime();
}
}
Component:
package com.kc2112.app.controllers;
import java.util.concurrent.Future;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.stereotype.Component;
#Component
public class MySampleService {
#Async
public Future<Boolean> callAsync(int taskCall) throws InterruptedException {
System.out.println("starting thread" + taskCall);
for (int i = 0; i < 10; i++) {
System.out.println("thread " + taskCall + " count is " + i);
}
return new AsyncResult<Boolean>(true);
}
}
Stopwatch:
package com.kc2112.app.controllers;
import org.apache.commons.lang.time.StopWatch;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
#Component
#Service
#Qualifier("stopwatch")
public class MyStopWatch extends StopWatch {
public MyStopWatch(){
super();
this.start();
}
}
I've tried a multitude of things, but it always prints results which are obviously not async.
public MySampleService mySampleService = new MySampleService();
This is the cause of your troubles. You must autowire the MySampleService into your controller instead of creating an instance yourself. That's the only way for Spring to wrap the component into an async proxy that will detect the annotation, intercept the method call, create a task and submit it to an executor.
YES!!!! After reading through this post:
Spring ThreadPoolTaskExecutor only running one thread
I made a few changes to my app class. The critical issue appears to be to set the core pool size. Here is the class with the line that fixed the issue...
Here's the spring docs on it:
http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/scheduling/concurrent/ThreadPoolTaskExecutor.html#setCorePoolSize-int-
package com.kc2112.app;
import com.kc2112.app.controllers.MyStopWatch;
import javax.annotation.Resource;
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.task.TaskExecutor;
import org.springframework.scheduling.annotation.AsyncConfigurer;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
#EnableAsync
#EnableScheduling
#Configuration
public class WebApp extends AbstractAnnotationConfigDispatcherServletInitializer implements AsyncConfigurer {
#Resource
#Qualifier("stopwatch")
public MyStopWatch stopwatch;
public WebApp() {
super();
stopwatch = new MyStopWatch();
}
#Override
protected Class<?>[] getRootConfigClasses() {
return new Class<?>[0];
}
#Override
protected Class<?>[] getServletConfigClasses() {
return new Class<?>[]{AppConfig.class};
}
#Override
protected String[] getServletMappings() {
return new String[]{"/"};
}
#Override
public TaskExecutor getAsyncExecutor() {
ThreadPoolTaskExecutor te = new ThreadPoolTaskExecutor();
te.setMaxPoolSize(25);
te.setThreadNamePrefix("LULExecutor-");
te.setCorePoolSize(25); //This was the critical line...
te.initialize();
return te;
}
#Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return null;
}
}