I'm wreting a SpringBoot web service use websocket to send message to client and using JPA to save data.
in project I use a thread to create a data ,and then use JPA to save it ,use Websocket to show data. But it doesn't work with a NullPointExecption.
this is my code:
#RestController
#ServerEndpoint("/websocket")
public class CrawlingController {
private final Logger logger = LoggerFactory.getLogger(CrawlingController.class);
#Autowired
private SimulateDataRepository simulateDataRepository;
private static GlobalStatus globalStatus = GlobalStatus.getInstance();
private Session session;
private static CopyOnWriteArraySet<CrawlingController> crawlingControllers =
new CopyOnWriteArraySet<>();
#OnOpen
public void onOpen(Session session) throws Exception {
this.session = session;
crawlingControllers.add(this);
String message = dataCrawling();
}
#OnMessage
public void onMessage(String message, Session session) throws IOException {
for (CrawlingController controller : crawlingControllers)
sendMessage(message);
}
#OnClose
public void onClose() {
crawlingControllers.remove(this);
if (crawlingControllers.size() == 0)
end();
session=null;
end();
}
private void sendMessage(String message) throws IOException {
this.session.getBasicRemote().sendText(message);
}
public void onError(Session session, Throwable error) {
logger.error(error.getMessage());
System.out.println("websocket found something error!");
}
#RequestMapping("/start")
public String dataCrawling() throws Exception {
if (!globalStatus.isDataCrawling) {
Process process = null;
synchronized (globalStatus) {
process = Utils.crawling();
globalStatus.crawlingProcss = process;
globalStatus.isDataCrawling = true;
}
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream()));
new Thread(() -> {
try {
stuffSimulate(bufferedReader);
} catch (IOException | ParseException e) {
logger.error(e.getMessage());
}
}).start();
return "start Finish!";
} else return "faild";
}
public void stuffSimulate(BufferedReader reader) throws IOException, ParseException {
line = reader.readLine();
while (globalStatus.isDataCrawling) {
SimulateData simulateData = new SimulateData();
.... ...
simulateData.setData(data.toString());
this.saveAndShow(simulateData);
}
}
}
}
private void saveAndShow(SimulateData simulateData) throws IOException {
simulateData = simulateDataRepository.saveAndFlush(simulateData);
SummaryData summaryData = SimulateService.obtainSummary(simulateData);
onMessage(summaryData.printSummary(),this.session);
summaryData.sout();
}
}
simulateDataRepository can be work when i use http://localhost:8080/start.
the mysql can get data.
But it cna't be work when i use websocket!!!
The error meaasge said that:
Exception in thread "Thread-5" java.lang.NullPointerException
at cn.linhos.controller.CrawlingController.saveAndShow(CrawlingController.java:293)
at cn.linhos.controller.CrawlingController.stuffSimulate(CrawlingController.java:172)
at cn.linhos.controller.CrawlingController.lambda$dataCrawling$0(CrawlingController.java:104)
at java.lang.Thread.run(Thread.java:748)
why simulateDataRepository can't saveAndFlush when websocket but can do it when i use "/start"?
how should i do to make websocket work ?
Related
If I send multiple commands to the same aggregate, only the first is handled.
Is this a configuration problem, or am I missing something?
The message I am getting after the 2nd command is send:
org.springframework.web.util.NestedServletException: Request processing failed; nested exception is org.axonframework.commandhandling.CommandExecutionException: Cannot invoke "Object.hashCode()" because "key" is null
The service method where I do my sending of the command is:
public void maakAanvraag() {
UUID aanvraagId = UUID.randomUUID();
commandGateway.sendAndWait(
VerwerkAanvraag.builder()
.aanvraagId(aanvraagId)
.build()
);
commandGateway.sendAndWait(
VerwerkPersoonsgegevensVastgesteld.builder()
.aanvraagId(aanvraagId)
.build()
);
commandGateway.sendAndWait(
VerwerkOrganisatiegegevensVastgesteld.builder()
.aanvraagId(aanvraagId)
.organisatieId(organisatieView.getOrganisatieId())
.rolOrganisatie(rolOrganisatie)
.build()
);
commandGateway.sendAndWait(
VerwerkBeperkingErkenningsdoelGematcht.builder()
.aanvraagId(aanvraagId)
.build());
}
The aggregate I am using is:
#Aggregate
#Getter
#NoArgsConstructor
public class Aanvraag {
public static final String META_DATA_ZAAKNUMMER = "aanvraag_zaaknummer";
#AggregateIdentifier
private UUID aanvraagId;
#CommandHandler
public Aanvraag(VerwerkAanvraag command) {
AanvraagGeregistreerd aanvraagGeregistreerd =
AanvraagGeregistreerd.builder()
.aanvraagId(command.getAanvraagId())
.build();
apply(aanvraagGeregistreerd, MetaData.with(META_DATA_ZAAKNUMMER, "123456789"));
}
#EventSourcingHandler
public void on(AanvraagGeregistreerd event) {
aanvraagId = event.getAanvraagId();
}
#CommandHandler
public void verwerkOrganisatiegegevensVastgesteld(VerwerkOrganisatiegegevensVastgesteld command) {
OrganisatiegegevensVastgesteld persoonsgegevensVastgesteld =
OrganisatiegegevensVastgesteld.builder()
.aanvraagId(command.getAanvraagId())
.build();
apply(persoonsgegevensVastgesteld);
}
#EventSourcingHandler
public void on(OrganisatiegegevensVastgesteld event) {
aanvraagId = event.getAanvraagId();
}
#CommandHandler
public void verwerkPersoonsgegevensVastgesteld(VerwerkPersoonsgegevensVastgesteld command) {
PersoonsgegevensVastgesteld persoonsgegevensVastgesteld =
PersoonsgegevensVastgesteld.builder()
.aanvraagId(command.getAanvraagId())
.build();
apply(persoonsgegevensVastgesteld);
}
#EventSourcingHandler
public void on(PersoonsgegevensVastgesteld event) {
aanvraagId = event.getAanvraagId();
}
#CommandHandler
public void verwerkBeperkingErkenningsdoelGematcht(VerwerkBeperkingErkenningsdoelGematcht command) {
BeperkingErkenningsdoelGematcht beperkingErkenningsdoelGematcht =
BeperkingErkenningsdoelGematcht.builder()
.aanvraagId(command.getAanvraagId())
.build();
apply(beperkingErkenningsdoelGematcht);
}
#EventSourcingHandler
public void on(BeperkingErkenningsdoelGematcht event) {
aanvraagId = event.getAanvraagId();
}
}
The project uses Spring Boot 2.6.6 with axon-spring-boot-starter 4.5.9
It al runs with Java Temurin 17.0.3
We solved the problem.
Issue had nothing to do with Axon.
The problem was an Logging interceptor.
After removing this log interceptor the Axon worked as expected.
UPDATE:
I have learned what I am looking to do is to use the Async within Retrofit with multiple queries too. I have updated my code, but I cannot get the async with the queries.
I am using Retrofit to make my data calls to a movie database and need to change the sort order depending on user settings. I am not clear how I could add this functionality to my interface.
sort_by=highest_rating.desc
or
sort_by=popularity.desc
Interface:
public interface MovieDatabaseApiCient {
#GET("/3/discover/movie")
void getData(#Query("api_key") String apiKey, #Query("sort_by") String sortByValue, Callback<MovieDbModel> response);
}
UPDATED API INTERFACE:
public interface MovieDatabaseApiCient {
#GET("/3/discover/movie?sort_by=popularity.desc&api_key=xxxxxxx")
void getMoviesByPopularityDesc(Callback<MovieDbModel> response);
#GET("/3/discover/movie?sort_by=vote_average_desc&api_key=xxxxxxxx")
void getMoviesByVotingDesc(Callback<MovieDbModel> response);
}
UPDATED DATA CALL THAT WORKS:
private void makeDataCall(String sortPreference) {
final RestAdapter restadapter = new RestAdapter.Builder().setEndpoint(ENDPOINT_URL).build();
MovieDatabaseApiCient apiLocation = restadapter.create(MovieDatabaseApiCient.class);
if (sortPreference.equals(this.getString(R.string.sort_order_popularity)) ){
apiLocation.getMoviesByPopularityDesc (new Callback<MovieDbModel>() {
#Override
public void success(MovieDbModel movieModels, Response response) {
movieDbResultsList = movieModels.getResults();
MoviesGridViewAdapter adapter = new MoviesGridViewAdapter(getApplicationContext(), R.layout.movie_gridview_item, movieDbResultsList);
gridView.setAdapter(adapter);
}
#Override
public void failure(RetrofitError error) {
Log.d("ERROR", error.toString());
Toast.makeText(getApplicationContext(), "Error: " + error.toString(), Toast.LENGTH_SHORT).show();
}
});
} else {
apiLocation.getMoviesByVotingDesc( new Callback<MovieDbModel>() {
#Override
public void success(MovieDbModel movieModels, Response response) {
movieDbResultsList = movieModels.getResults();
MoviesGridViewAdapter adapter = new MoviesGridViewAdapter(getApplicationContext(), R.layout.movie_gridview_item, movieDbResultsList);
gridView.setAdapter(adapter);
}
#Override
public void failure(RetrofitError error) {
Log.d("ERROR", error.toString());
Toast.makeText(getApplicationContext(), "Error: " + error.toString(), Toast.LENGTH_SHORT).show();
}
});
}
}
My call for the data:
private void makeDataCall (String apiKey, String sortPreference) {
final RestAdapter restadapter = new RestAdapter.Builder().setEndpoint(ENDPOINT_URL).build();
MovieDatabaseApiCient apiLocation = restadapter.create(MovieDatabaseApiCient.class);
apiLocation.getData(apiKey, sortPreference, new Callback<MovieDbModel>){
#Override
public void success(MovieDbModel movieModels, Response response) {
movieDbResultsList = movieModels.getResults();
MoviesGridViewAdapter adapter = new MoviesGridViewAdapter(getApplicationContext(), R.layout.movie_gridview_item, movieDbResultsList);
gridView.setAdapter(adapter);
}
#Override
public void failure(RetrofitError error) {
Log.d("ERROR", error.toString());
Toast.makeText(getApplicationContext(), "Error: " + error.toString(), Toast.LENGTH_SHORT).show();
}
});
}
I found a way to do Synchronously, but not asynchronously.
From your question and comment, IHMO, you should import retrofit.Callback; instead of import com.squareup.okhttp.Callback;
My code as the following has no compile error:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// creating a RestAdapter using the custom client
RestAdapter restAdapter = new RestAdapter.Builder()
.setEndpoint(API_URL_BASE)
.setLogLevel(RestAdapter.LogLevel.FULL)
.setClient(new OkClient(mOkHttpClient))
.build();
WebService webService = restAdapter.create(WebService.class);
retrofit.Callback<GetRoleData> callback = new Callback<GetRoleData>() {
#Override
public void success(GetRoleData getRoleData, retrofit.client.Response response) {
}
#Override
public void failure(RetrofitError error) {
}
};
webService.getData("api_key", "sort_by", callback);
}
Interface:
public interface WebService {
#GET("/3/discover/movie")
void getData(#Query("api_key") String apiKey, #Query("sort_by") String sortByValue, Callback<GetRoleData> response);
}
So, please check your code again
I have a huge MS Access database file (aprrox. 1gb) and about 5 different GUI (FXML). Each fxml contains data from different tables. I am using ucanaccess to connect with database. Now I am having problem in connecting with database. I never get connection. It works fine with smaller database file. I am using service and task for background thread. Could someone tell me what can be the best approach to overcome this problem.
private Service backgroundService;
private Connection ucaConn;
#FXML
private void handleButtonAction(ActionEvent event) {
backgroundService = new Service() {
#Override
protected Task createTask() {
return new Task() {
#Override
protected Object call() throws Exception {
try {
ucaConn = getUcanaccessConnection(DataCarrier.getInstance().getDatabaseLocation());
} catch (SQLException | IOException ex) {
Logger.getLogger(HomeController.class.getName()).log(Level.SEVERE, null, ex);
}
return null;
}
};
}
};
backgroundService.setOnSucceeded(new EventHandler<WorkerStateEvent>() {
#Override
public void handle(WorkerStateEvent event) {
System.out.println("Done");
errorMessage.textProperty().unbind();
String timeStamp = new SimpleDateFormat("mm:ss").format(Calendar.getInstance().getTime());
System.out.println("End time: " + timeStamp);
}
});
errorMessage.textProperty().bind(backgroundService.messageProperty());
backgroundService.restart();
}
}
}
private static Connection getUcanaccessConnection(String pathNewDB) throws SQLException,
IOException {
String url = UcanaccessDriver.URL_PREFIX + pathNewDB + ";newDatabaseVersion=V2003";
return DriverManager.getConnection(url, "sa", "");
}
i'm currently have a look a springboot undertow and it's not really clear (for me) how to dispatch an incoming http request to a worker thread for blocking operation handling.
Looking at the class UndertowEmbeddedServletContainer.class, it look like there is no way to have this behaviour since the only HttpHandler is a ServletHandler, that allow #Controller configurations
private Undertow createUndertowServer() {
try {
HttpHandler servletHandler = this.manager.start();
this.builder.setHandler(getContextHandler(servletHandler));
return this.builder.build();
}
catch (ServletException ex) {
throw new EmbeddedServletContainerException(
"Unable to start embdedded Undertow", ex);
}
}
private HttpHandler getContextHandler(HttpHandler servletHandler) {
if (StringUtils.isEmpty(this.contextPath)) {
return servletHandler;
}
return Handlers.path().addPrefixPath(this.contextPath, servletHandler);
}
By default, in undertow all requests are handled by IO-Thread for non blocking operations.
Does this mean that every #Controller executions will be processed by a non blocking thread ? or is there a solution to chose from IO-THREAD or WORKER-THREAD ?
I try to write a workaround, but this code is pretty uggly, and maybe someone has a better solution:
BlockingHandler.class
#Target({ElementType.TYPE})
#Retention(RetentionPolicy.RUNTIME)
#Documented
public #interface BlockingHandler {
String contextPath() default "/";
}
UndertowInitializer.class
public class UndertowInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
#Override
public void initialize(ConfigurableApplicationContext configurableApplicationContext) {
configurableApplicationContext.addBeanFactoryPostProcessor(new UndertowHandlerPostProcessor());
}
}
UndertowHandlerPostProcessor.class
public class UndertowHandlerPostProcessor implements BeanDefinitionRegistryPostProcessor {
#Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanDefinitionRegistry) throws BeansException {
ClassPathScanningCandidateComponentProvider scanner = new ClassPathScanningCandidateComponentProvider(false);
scanner.addIncludeFilter(new AnnotationTypeFilter(BlockingHandler.class));
for (BeanDefinition beanDefinition : scanner.findCandidateComponents("org.me.lah")){
try{
Class clazz = Class.forName(beanDefinition.getBeanClassName());
beanDefinitionRegistry.registerBeanDefinition(clazz.getSimpleName(), beanDefinition);
} catch (ClassNotFoundException e) {
throw new BeanCreationException(format("Unable to create bean %s", beanDefinition.getBeanClassName()), e);
}
}
}
#Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
//no need to post process defined bean
}
}
override UndertowEmbeddedServletContainerFactory.class
public class UndertowEmbeddedServletContainerFactory extends AbstractEmbeddedServletContainerFactory implements ResourceLoaderAware, ApplicationContextAware {
private ApplicationContext applicationContext;
#Override
public EmbeddedServletContainer getEmbeddedServletContainer(ServletContextInitializer... initializers) {
DeploymentManager manager = createDeploymentManager(initializers);
int port = getPort();
if (port == 0) {
port = SocketUtils.findAvailableTcpPort(40000);
}
Undertow.Builder builder = createBuilder(port);
Map<String, Object> handlers = applicationContext.getBeansWithAnnotation(BlockingHandler.class);
return new UndertowEmbeddedServletContainer(builder, manager, getContextPath(),
port, port >= 0, handlers);
}
#Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
}
...
override UndertowEmbeddedServletContainer.class
public UndertowEmbeddedServletContainer(Builder builder, DeploymentManager manager,
String contextPath, int port, boolean autoStart, Map<String, Object> handlers) {
this.builder = builder;
this.manager = manager;
this.contextPath = contextPath;
this.port = port;
this.autoStart = autoStart;
this.handlers = handlers;
}
private Undertow createUndertowServer() {
try {
HttpHandler servletHandler = this.manager.start();
String path = this.contextPath.isEmpty() ? "/" : this.contextPath;
PathHandler pathHandler = Handlers.path().addPrefixPath(path, servletHandler);
for(Entry<String, Object> entry : handlers.entrySet()){
Annotation annotation = entry.getValue().getClass().getDeclaredAnnotation(BlockingHandler.class);
System.out.println(((BlockingHandler) annotation).contextPath());
pathHandler.addPrefixPath(((BlockingHandler) annotation).contextPath(), (HttpHandler) entry.getValue());
}
this.builder.setHandler(pathHandler);
return this.builder.build();
}
catch (ServletException ex) {
throw new EmbeddedServletContainerException(
"Unable to start embdedded Undertow", ex);
}
}
set initializer to the application context
public static void main(String[] args) {
new SpringApplicationBuilder(Application.class).initializers(new UndertowInitializer()).run(args);
}
finaly create a HttpHandler that dispatch to worker thread
#BlockingHandler(contextPath = "/blocking/test")
public class DatabaseHandler implements HttpHandler {
#Autowired
private EchoService echoService;
#Override
public void handleRequest(HttpServerExchange httpServerExchange) throws Exception {
if(httpServerExchange.isInIoThread()){
httpServerExchange.dispatch();
}
echoService.getMessage("my message");
}
}
As you can see, my "solution" is really heavy, and i would really appreciate any help to simplify it a lot.
Thank you
You don't need to do anything.
Spring Boot's default Undertow configuration uses Undertow's ServletInitialHandler in front of Spring MVC's DispatcherServlet. This handler performs the exchange.isInIoThread() check and calls dispatch() if necessary.
If you place a breakpoint in your #Controller, you'll see that it's called on a thread named XNIO-1 task-n which is a worker thread (the IO threads are named XNIO-1 I/O-n).
I'm trying to develop custom Flume source which can receive custom UDP packets.
Here is my code:
public class XvlrUdpSource extends AbstractSource
implements EventDrivenSource, Configurable {
private static final Logger LOG = LoggerFactory.getLogger(XvlrUdpSource.class);
private int port;
private String host;
private Channel nettyChannel;
private static final Logger logger = LoggerFactory.getLogger(XvlrUdpSource.class);
private CounterGroup counterGroup = new CounterGroup();
public class XvlrUpdHander extends SimpleChannelHandler {
#Override
public void messageReceived(ChannelHandlerContext ctx, MessageEvent mEvent) {
try {
System.out.println("class: "+ mEvent.getMessage().getClass());
/** ChannelBuffer holds just first 768 bytes of the whole input UDP packet*/
ChannelBuffer channelBuffer = (ChannelBuffer)mEvent.getMessage();
Event xvlrPacketEvent = EventBuilder.withBody( ((ChannelBuffer)mEvent.getMessage()).array());
System.out.println("Length is:["+xvlrPacketEvent.getBody().length+"]");
//Event e = syslogUtils.extractEvent((ChannelBuffer)mEvent.getMessage());
if(xvlrPacketEvent == null){
return;
}
getChannelProcessor().processEvent(xvlrPacketEvent);
counterGroup.incrementAndGet("events.success");
} catch (ChannelException ex) {
counterGroup.incrementAndGet("events.dropped");
logger.error("Error writting to channel", ex);
return;
}
}
}
#Override
public void start() {
ConnectionlessBootstrap serverBootstrap = new ConnectionlessBootstrap
(new OioDatagramChannelFactory(Executors.newCachedThreadPool()));
final XvlrUpdHander handler = new XvlrUpdHander();
serverBootstrap.setPipelineFactory(new ChannelPipelineFactory() {
#Override
public ChannelPipeline getPipeline() {
return Channels.pipeline(handler);
}
});
if (host == null) {
nettyChannel = serverBootstrap.bind(new InetSocketAddress(port));
} else {
nettyChannel = serverBootstrap.bind(new InetSocketAddress(host, port));
}
super.start();
}
#Override
public void stop() {
logger.info("Syslog UDP Source stopping...");
logger.info("Metrics:{}", counterGroup);
if (nettyChannel != null) {
nettyChannel.close();
try {
nettyChannel.getCloseFuture().await(60, TimeUnit.SECONDS);
} catch (InterruptedException e) {
logger.warn("netty server stop interrupted", e);
} finally {
nettyChannel = null;
}
}
super.stop();
}
#Override
public void configure(Context context) {
Configurables.ensureRequiredNonNull(
context, "port");//SyslogSourceConfigurationConstants.CONFIG_PORT);
port = context.getInteger("port");//SyslogSourceConfigurationConstants.CONFIG_PORT);
host = context.getString("host");//SyslogSourceConfigurationConstants.CONFIG_HOST);
//formaterProp = context.getSubProperties("PROP");//SyslogSourceConfigurationConstants.CONFIG_FORMAT_PREFIX);
}
}
I did debug on messageRecieved and see in stacktrace that here:
/**
* Sends a {#code "messageReceived"} event to the first
* {#link ChannelUpstreamHandler} in the {#link ChannelPipeline} of
* the specified {#link Channel} belongs.
*
* #param message the received message
* #param remoteAddress the remote address where the received message
* came from
*/
public static void fireMessageReceived(Channel channel, Object message, SocketAddress remoteAddress) {
channel.getPipeline().sendUpstream(
new UpstreamMessageEvent(channel, message, remoteAddress));
}
My Object message is already 768 bytes length.
The root is here org.jboss.netty.channel.socket.oio.OioDatagramWorker:
byte[] buf = new byte[predictor.nextReceiveBufferSize()];
DatagramPacket packet = new DatagramPacket(buf, buf.length);
Predictor sets buffer size to 768
Then:
fireMessageReceived(
channel,
channel.getConfig().getBufferFactory().getBuffer(buf, 0, packet.getLength()),
packet.getSocketAddress());
I do get only first 768 bytes.
is there any chance to change predictor behavior?
I've found this topic:
Netty Different Pipeline Per UDP Datagram
it's possible to "inject" predictor with desired behavior using special properties.
So full solution is:
public class XvlrUdpSource extends AbstractSource
implements EventDrivenSource, Configurable {
private static final Logger LOG = LoggerFactory.getLogger(XvlrUdpSource.class);
private int port;
private String host;
private Channel nettyChannel;
private CounterGroup counterGroup = new CounterGroup();
public class XvlrUpdHander extends SimpleChannelHandler {
#Override
public void messageReceived(ChannelHandlerContext ctx, MessageEvent mEvent) {
try {
ChannelBuffer channelBuffer = (ChannelBuffer)mEvent.getMessage();
int actualSizeOfUdpPacket = channelBuffer.readableBytes();
byte[] body = Arrays.copyOf(channelBuffer.array(), actualSizeOfUdpPacket);
Event xvlrPacketEvent = EventBuilder.withBody(body);
LOG.debug("Event.body length is: {} ", xvlrPacketEvent.getBody().length);
if(xvlrPacketEvent == null){
return;
}
getChannelProcessor().processEvent(xvlrPacketEvent);
counterGroup.incrementAndGet("events.success");
} catch (ChannelException ex) {
counterGroup.incrementAndGet("events.dropped");
LOG.error("Error writting to channel", ex);
return;
}
}
}
#Override
public void start() {
OioDatagramChannelFactory oioDatagramChannelFactory = new OioDatagramChannelFactory( Executors.newCachedThreadPool());
ConnectionlessBootstrap serverBootstrap = new ConnectionlessBootstrap(oioDatagramChannelFactory);
serverBootstrap.setOption("sendBufferSize", 65536);
serverBootstrap.setOption("receiveBufferSize", 65536);
serverBootstrap.setOption("receiveBufferSizePredictorFactory",
new AdaptiveReceiveBufferSizePredictorFactory(8192, 8192, 16384));
final XvlrUpdHander handler = new XvlrUpdHander();
serverBootstrap.setPipelineFactory(new ChannelPipelineFactory() {
#Override
public ChannelPipeline getPipeline() {
return Channels.pipeline(handler);
}
});
if (host == null) {
nettyChannel = serverBootstrap.bind(new InetSocketAddress(port));
} else {
nettyChannel = serverBootstrap.bind(new InetSocketAddress(host, port));
}
}
#Override
public void stop() {
LOG.info("Syslog UDP Source stopping...");
LOG.info("Metrics:{}", counterGroup);
if (nettyChannel != null) {
nettyChannel.close();
try {
nettyChannel.getCloseFuture().await(60, TimeUnit.SECONDS);
} catch (InterruptedException e) {
LOG.warn("netty server stop interrupted", e);
} finally {
nettyChannel = null;
}
}
super.stop();
}
#Override
public void configure(Context context) {
Configurables.ensureRequiredNonNull(context, "port");
port = context.getInteger("port");
host = context.getString("host");
}
}
Either you are sending 768 bytes or the receiving buffer is only 768 bytes long. It certainly has nothing to do with carriage returns, unless there is some buggy handling of them in your code.