Azure - EventHub Consumer Binding With AMQP Web Sockets - spring-boot

I'm trying to set up a very basic proof of concept to link a Spring application to an Azure Event Hub. I keep getting this log in my startup:
[2021-11-17 16:49:18.343 ERROR 25816 --- [ main] o.s.cloud.stream.binding.BindingService : Failed to create consumer binding; retrying in 30 seconds
...
Caused by: java.lang.IllegalArgumentException: Cannot use a proxy when TransportType is not AMQP Web Sockets.
at com.azure.messaging.eventhubs.EventHubClientBuilder.getConnectionOptions(EventHubClientBuilder.java:764) ~[azure-messaging-eventhubs-5.10.2.jar:5.10.2]
at com.azure.messaging.eventhubs.EventHubClientBuilder.buildConnectionProcessor(EventHubClientBuilder.java:705) ~[azure-messaging-eventhubs-5.10.2.jar:5.10.2]
at com.azure.messaging.eventhubs.EventHubClientBuilder.buildAsyncClient(EventHubClientBuilder.java:638) ~[azure-messaging-eventhubs-5.10.2.jar:5.10.2]
at com.azure.messaging.eventhubs.EventProcessorClient.<init>(EventProcessorClient.java:89) ~[azure-messaging-eventhubs-5.10.2.jar:5.10.2]
at com.azure.messaging.eventhubs.EventProcessorClientBuilder.buildEventProcessorClient(EventProcessorClientBuilder.java:585) ~[azure-messaging-eventhubs-5.10.2.jar:5.10.2]
...
This is despite the fact that I defined beans for EventHubProducerAsyncClient, EventHubConsumerAsyncClient, and EventProcessorClient that explicitly set the transport type to AMQP_WEB_SOCKETS. See here:
Producer:
#Bean
public EventHubProducerAsyncClient eventHubProducerAsyncClient() {
return new EventHubClientBuilder()
.connectionString(connectionString)
.proxyOptions(new ProxyOptions(
ProxyAuthenticationType.NONE,
new Proxy(Proxy.Type.HTTP, new InetSocketAddress("my proxy address", 8080)),
null, null
))
.transportType(AmqpTransportType.AMQP_WEB_SOCKETS)
.buildAsyncProducerClient();
}
Consumer:
#Bean
public EventHubConsumerAsyncClient eventHubConsumerAsyncClient() {
return new EventHubClientBuilder()
.connectionString(connectionString)
.proxyOptions(new ProxyOptions(
ProxyAuthenticationType.NONE,
new Proxy(Proxy.Type.HTTP, new InetSocketAddress("my proxy address", 8080)),
null, null
))
.transportType(AmqpTransportType.AMQP_WEB_SOCKETS)
.consumerGroup(DEFAULT_CONSUMER_GROUP_NAME)
.buildAsyncConsumerClient();
}
EventProcessor:
private static void onEvent(EventContext eventContext) {
PartitionContext partition = eventContext.getPartitionContext();
LOGGER.info("Received events from partition: " + partition.getPartitionId());
EventData event = eventContext.getEventData();
LOGGER.info("Sequence number: " + event.getSequenceNumber());
LOGGER.info("Contents: " + new String(event.getBody(), StandardCharsets.UTF_8));
}
#Bean
public EventProcessorClient eventProcessorClient() {
BlobContainerAsyncClient blobClient = new BlobContainerClientBuilder()
.connectionString(storageConnectionString)
.containerName(storageContainerName)
.buildAsyncClient();
return new EventProcessorClientBuilder()
.connectionString(connectionString)
.consumerGroup(DEFAULT_CONSUMER_GROUP_NAME)
.checkpointStore(new BlobCheckpointStore(blobClient))
.processEvent(eventContext -> onEvent(eventContext))
.processError(context -> {
LOGGER.error("Error occurred on partition: %s. Error: %s%n",
context.getPartitionContext().getPartitionId(), context.getThrowable());
})
.processPartitionInitialization(initializationContext -> {
LOGGER.info("Started receiving on partition: %s%n",
initializationContext.getPartitionContext().getPartitionId());
})
.processPartitionClose(closeContext -> {
LOGGER.info("Stopped receiving on partition: %s. Reason: %s%n",
closeContext.getPartitionContext().getPartitionId(),
closeContext.getCloseReason());
})
.proxyOptions(new ProxyOptions(
ProxyAuthenticationType.NONE,
new Proxy(Proxy.Type.HTTP, new InetSocketAddress("my proxy address", 8080)),
null, null
))
.transportType(AmqpTransportType.AMQP_WEB_SOCKETS)
.buildEventProcessorClient();
}
Am I missing something obvious here? I don't understand how it can complain about TransportType not being AMQP Web Sockets when its explicitly defined.

Related

How to use RemoteFileTemplate<SmbFile> in Spring integration?

I've got a Spring #Component where a SmbSessionFactory is injected to create a RemoteFileTemplate<SmbFile>. When my application runs, this piece of code is called multiple times:
public void process(Message myMessage, String filename) {
StopWatch stopWatch = StopWatch.createStarted();
byte[] bytes = marshallMessage(myMessage);
String destination = smbConfig.getDir() + filename + ".xml";
if (log.isDebugEnabled()) {
log.debug("Result: {}", new String(bytes));
}
Optional<IOException> optionalEx =
remoteFileTemplate.execute(
session -> {
try (InputStream inputStream = new ByteArrayInputStream(bytes)) {
session.write(inputStream, destination);
} catch (IOException e1) {
return Optional.of(e1);
}
return Optional.empty();
});
log.info("processed Message in {}", stopWatch.formatTime());
optionalEx.ifPresent(
ioe -> {
throw new UncheckedIOException(ioe);
});
}
this works (i.e. the file is written) and all is fine. Except that I see warnings appearing in my log:
DEBUG my.package.MyClass Result: <?xml version="1.0" encoding="UTF-8" standalone="yes"?>....
INFO org.springframework.integration.smb.session.SmbSessionFactory SMB share init: XXX
WARN jcifs.smb.SmbResourceLocatorImpl Path consumed out of range 15
WARN jcifs.smb.SmbTreeImpl Disconnected tree while still in use SmbTree[share=XXX,service=null,tid=1,inDfs=true,inDomainDfs=true,connectionState=3,usage=2]
INFO org.springframework.integration.smb.session.SmbSession Successfully wrote remote file [path\to\myfile.xml].
WARN jcifs.smb.SmbSessionImpl Logging off session while still in use SmbSession[credentials=XXX,targetHost=XXX,targetDomain=XXX,uid=0,connectionState=3,usage=1]:[SmbTree[share=XXX,service=null,tid=1,inDfs=false,inDomainDfs=false,connectionState=0,usage=1], SmbTree[share=XXX,service=null,tid=5,inDfs=false,inDomainDfs=false,connectionState=2,usage=0]]
jcifs.smb.SmbTransportImpl Disconnecting transport while still in use Transport746[XXX/999.999.999.999:445,state=5,signingEnforced=false,usage=1]: [SmbSession[credentials=XXX,targetHost=XXX,targetDomain=XXX,uid=0,connectionState=2,usage=1], SmbSession[credentials=XXX,targetHost=XXX,targetDomain=null,uid=0,connectionState=2,usage=0]]
INFO my.package.MyClass processed Message in 00:00:00.268
The process method is called from a Rest method, which does little else.
What am I doing wrong here?

Vertx amqp client doesnt reconnect on broker down

I am trying to write a program to pull messages from a message broker via Vert.x AMQP client. I want to make the program try to reconnect on broker down. Currently if I turn off the broker container, the program doesn't react. Below is my code.. What do I miss ?
public class BrokerConnector {
public void consumeEventsQueue() {
AmqpClientOptions options = new AmqpClientOptions()
.setHost("localhost")
.setPort(5672)
.setUsername("")
.setPassword("");
AmqpClient amqpClient = AmqpClient.create(options);
amqpClient.connect(con -> {
if (con.failed()) {
System.out.println("Unable to connect to the broker");
} else {
System.out.println("Connection succeeded");
}
});
amqpClient.createReceiver("MY_QUEUE",
done -> {
if (done.failed()) {
System.out.println("Unable to create receiver");
} else {
AmqpReceiver receiver = done.result();
receiver.handler(msg -> {
System.out.println("Received " + msg.bodyAsString());
});
}
}
);
}
}
To my knowledge (and from peeking at the source) the vertx AMQP client doesn't have automatic client reconnect so it seems quite normal that on loss of connection you application is failing. The client exposes an exception handler that you can hook and recreate your client resources from when the connection drops. There are some clients for AMQP that do have automatic reconnect built in like Qpid JMS or the Qpid protonj2 client.

Setting mail.smtp.connectiontimeout longens requests when working with office 365

We are sending mails in an email service with org.springframework.mail.javamail.JavaMailSender via an office 365 account and SMTP and set the following parameters in application.yml:
spring:
mail:
host: ${EMAIL_HOST:smtp.office365.com}
port: ${EMAIL_PORT:587}
username: ${EMAIL_USERNAME}
password: ${EMAIL_PASSWORD}
properties:
mail:
smtp:
auth: true
connectiontimeout: 5000
timeout: 5000
writetimeout: 5000
starttls:
enable: true
socketFactory:
port: 465
class: javax.net.ssl.SSLSocketFactory
The strange thing is: if we set the connectiontimeout to 5s, the service gets a response after 5s. If we set it to 20s, the o365 responds after 20s.
My expectation is that <connectiontimeout> is the maximum amount of time, that the sending may take and not the actual time.
Funny thing is that when setting another provider than office365, connectiontimeout works as expected.
Does anyone have this issue as well and maybe know how to solve that?
Our sender service:
#PostMapping
#ResponseStatus(HttpStatus.ACCEPTED)
public void sendMail(#RequestHeader(name = "X-API-KEY", required = true) String requestApiKey, #Valid #RequestBody EmailSendRequest email, HttpServletResponse response) {
if(!apiKey.equals(requestApiKey)){
LOGGER.error("Unauthorized api key" + requestApiKey);
throw new ResponseStatusException(HttpStatus.UNAUTHORIZED);
}
try {
LOGGER.info("Received request to send mail Subject=[{}] To=[{}] From=[{}]", email.getSubject(), email.getTo(), email.getFrom());
MimeMessage message = mailSender.createMimeMessage();
message.setFrom(new InternetAddress(email.getFrom().getEmail()));
message.addRecipients(Message.RecipientType.TO, toAddressArray(email.getTo()));
message.addRecipients(Message.RecipientType.CC, toAddressArray(email.getCc()));
message.addRecipients(Message.RecipientType.BCC, toAddressArray(email.getBcc()));
message.setSubject(email.getSubject());
message.setSentDate(new Date());
Multipart multipart = new MimeMultipart();
MimeBodyPart messageText = new MimeBodyPart();
messageText.setContent(email.getContent().getValue(),
email.getContent().getType() == null ? DEFAULT_CONTENT_MIMETYPE : email.getContent().getType());
multipart.addBodyPart(messageText);
addAttachments(multipart, email.getAttachments());
message.setContent(multipart);
if(message.getRecipients(Message.RecipientType.TO) != null ||
message.getRecipients(Message.RecipientType.CC) != null ||
message.getRecipients(Message.RecipientType.BCC) != null)
{
mailSender.send(message);
}
else {
LOGGER.warn("Email not send! No recipients or all ignored.");
response.setHeader("X-Ignored","true");
}
LOGGER.info("Mail Subject=[{}] To=[{}}] From=[{}] successfully sent.",email.getSubject(),email.getTo(),email.getFrom());
} catch (MessagingException e) {
LOGGER.error("Error sending mail Subject=[{}] To=[{}] From=[{}]:", email.getSubject(), email.getTo(), email.getFrom(), e);
throw new ResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR);
} catch (MailSendException mailSendException) {
Exception[] exceptions = mailSendException.getMessageExceptions();
for (Exception e : exceptions){
if (e instanceof SMTPSendFailedException && (((SMTPSendFailedException)e).getReturnCode() == 554)){
LOGGER.error("Error sending mail Subject=[{}] To=[{}] From=[{}]: This sender mail address is not allowed.", email.getSubject(), email.getTo(), email.getFrom());
throw new ResponseStatusException(HttpStatus.FORBIDDEN);
}
}
LOGGER.error("Error sending mail Subject=[{}] To=[{}] From=[{}]:", email.getSubject(), email.getTo(), email.getFrom(), mailSendException);
throw new ResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR);
} catch (MailAuthenticationException e) {
LOGGER.error("Error sending mail Subject=[{}] To=[{}] From=[{}]: Wrong SMTP login credentials provided. \nMSG:{}", email.getSubject(), email.getTo(), email.getFrom(),e.getMessage());
throw new ResponseStatusException(HttpStatus.NETWORK_AUTHENTICATION_REQUIRED);
}
}
It seems, that the SocketFactory was responsible for this behaviour. Removing the following lines from application.yml makes the application work as expected:
socketFactory:
port: 465
class: javax.net.ssl.SSLSocketFactory

Can't seem to send email with jhipster application

I'm trying to make a simple form that when submited sends and email to a fixed email.
I'm using spring and i've searched on how to configure the application.yml and i'm using the mailsend method that seems to have been generated with my jhipster application.
I've built my FE service to connect to the back end :
sendForm(): Observable<any>{
return this.http.post(SERVER_API_URL + 'api/sendForm', "");
}
i've built the onsubmit method to make the subscribe to the method above:
onSubmit() {
this.auth.sendForm().subscribe( data => {
console.log(data);
})
}
i've hard coded the mail resource just to mock an email to make sure its working:
#PostMapping("/sendForm")
public void sendForm() {
this.mailService.sendEmail("mymail#gmail.com","Header","texto",false,true);
}
the sendMail method that im sending the information for the mail submition is autogenerated and I believe it should be working
#Async
public void sendEmail(String to, String subject, String content, boolean isMultipart, boolean isHtml) {
log.debug("Send email[multipart '{}' and html '{}'] to '{}' with subject '{}' and content={}",
isMultipart, isHtml, to, subject, content);
// Prepare message using a Spring helper
MimeMessage mimeMessage = javaMailSender.createMimeMessage();
try {
MimeMessageHelper message = new MimeMessageHelper(mimeMessage, isMultipart, StandardCharsets.UTF_8.name());
message.setTo(to);
message.setFrom(jHipsterProperties.getMail().getFrom());
message.setSubject(subject);
message.setText(content, isHtml);
javaMailSender.send(mimeMessage);
log.debug("Sent email to User '{}'", to);
} catch (Exception e) {
if (log.isDebugEnabled()) {
log.warn("Email could not be sent to user '{}'", to, e);
} else {
log.warn("Email could not be sent to user '{}': {}", to, e.getMessage());
}
}
}
and heres my application-dev.yml (i'm still on dev)
spring:
profiles:
active: dev
mail:
host: smtp.gmail.com
port: 587
username: gmailuserid#gmail.com #Replace this field with your Gmail username.
password: ************ #Replace this field with your Gmail password.
protocol: smtp
tls: true
properties.mail.smtp:
auth: true
starttls.enable: true
ssl.trust: smtp.gmail.com
the errors im getting goes as follows:
org.springframework.mail.MailSendException: Mail server connection failed; nested exception is com.sun.mail.util.MailConnectException: Couldn't connect to host, port: localh
ost, 25; timeout -1;
nested exception is:
java.net.ConnectException: Connection refused: connect. Failed messages: com.sun.mail.util.MailConnectException: Couldn't connect to host, port: localhost, 25; timeo
ut -1;
All I expect is a mail with the mock i've used and I cant seem to be able to put this working.
I hope i've not made the post to long and that everything is well explained.
Thank you in advance for anyone willing to help
Apparently somewhy the properties-prod.yml wasnt being loaded to the server. I had to create a config file with all the configurations for it to work

Deleting all messages in JMS queue in Widlfy 9

I am trying to remove messages from JMS queue on Wildfly 9.0.2 (JBoss) using JMX, see following code:
MBeanServer server = ManagementFactory.getPlatformMBeanServer();
try {
String name = "jboss.as.expr:subsystem=messaging,hornetq-server=default,jms-queue=MyQueue";
ObjectName objectName = new ObjectName(objectNameString);
String result = (String) server.invoke(objectName, "removeMessages", new Object[]{null},
new String[]{"java.lang.String"});
return result;
} catch (MalformedObjectNameException | InstanceNotFoundException | MBeanException | ReflectionException ignored) {
log.errorv(ignored, "Error removing messages from JMS queue [{0}]", name);
return null;
}
There is an active consumer on that queue. The code runs without exception and returns string "0", but no messages are actually removed. I tried also to use some value as message filter (*), but got failure:
javax.management.ReflectionException: "HQ119020: Invalid filter: *"
Any idea how to remove the messages?

Resources