Replace Anonymous Inner Class By Lambda. How does this work? - soap

While sending a SOAP message, i wanted to add some custom headers so i did like below;
JAXBElement<ConfigurationResponse> jaxbElementResponse = (JAXBElement<ConfigurationResponse>) getWebServiceTemplate()
.marshalSendAndReceive(urlToSend,
new ObjectFactory().createConfigurationRequest(request),
new WebServiceMessageCallback() {
#Override
public void doWithMessage(WebServiceMessage message) throws IOException, TransformerException {
SaajSoapMessage soapMessage = (SaajSoapMessage) message;
SoapHeaderElement id = soapMessage.getSoapHeader().addHeaderElement(new QName(uri, localpart, prefix));
id.setText(text);
}
});
But "NetBeans" tell me i can use lambda expr. So if i do the change, it is like,
JAXBElement<ConfigurationResponse> jaxbElementResponse = (JAXBElement<ConfigurationResponse>) getWebServiceTemplate()
.marshalSendAndReceive(urlToSend,
new ObjectFactory().createConfigurationRequest(request), (WebServiceMessage message) -> {
SaajSoapMessage soapMessage = (SaajSoapMessage) message;
SoapHeaderElement id = soapMessage.getSoapHeader().addHeaderElement(new QName(uri, localpart, prefix));
id.setText(text);
});
Are both same? If yes, how this works?

A Lambda expression is syntactical sugar over an anonymous class. A Lambda can be used where ever the type is an functional interface, which is an interface which declares only one abstract method. The Lambda expression provides the implementation of that single method.
For your case the WebServiceMessageCallback is a functional interface. It has the one abstract method: doWithMessage(...). The Lambda expression you created provides the implementation of that method.

Related

How to create a ClassTag<Dataset<Row>> in Java

I am writing a spark-sql query that needs to broadcast something.
Now I have some codes like this. The generic type parameter is wrong.
final Broadcast<Dataset<Row>> b = sparkSession.sparkContext().broadcast(
sparkSession.sql("My SQL"),
classTag(Dataset.class)
);
The createTag method:
private static <T> ClassTag<T> classTag(final Class<T> clazz) {
return scala.reflect.ClassManifestFactory.fromClass(clazz);
}
How can I make the code compiles?
You'll have to cast it in a kind of ugly way:
classTag((Class<Dataset<Row>>) (Class<?>) Dataset.class)
Unfortunately, I don't know a better solution.

How can I access to the acknowledge entity in spring cloud sqs without setting custom argument resolvers?

In order to have access to events like S3EventNotification we need to specify a custom argument resolver in in the QueueMessageHandlerFactory. But since the order in which those argument resolver are evaluated matters it forces me to have a list that has every argument resolver twice. Is it possible to avoid this?
I am trying to read from a queue where events are generated by amazon itself.
In this case I need to set
messageConverter.setStrictContentTypeMatch(false);
as explained here: https://cloud.spring.io/spring-cloud-aws/1.2.x/multi/multi__messaging.html#_consuming_aws_event_messages_with_amazon_sqs
In the method however I needed to use Acknowledge, Visibility, and header method parameters but those were not passed correctly unless I redefine all the possible argument resolver in the configuration.
So to have the following method signature:
#SqsListener(value = "${my-queue-name}", deletionPolicy = NEVER)
public void processRequest(
#Payload S3EventNotification s3EventNotificationRecord,
#Header("ApproximateReceiveCount") final int receiveCount,
Acknowledgment acknowledgment,
Visibility visibility) {
// do some stuff and decide to acknowledge or extend visibility
}
I was forced to write this custom configuration like:
#Configuration
public class AmazonSQSConfig {
private static final String ACKNOWLEDGMENT = "Acknowledgment";
private static final String VISIBILITY = "Visibility";
#Bean
public QueueMessageHandlerFactory queueMessageHandlerFactory() {
QueueMessageHandlerFactory factory = new QueueMessageHandlerFactory();
factory.setArgumentResolvers(initArgumentResolvers());
return factory;
}
private List<HandlerMethodArgumentResolver> initArgumentResolvers() {
MappingJackson2MessageConverter messageConverter = new MappingJackson2MessageConverter();
messageConverter.setStrictContentTypeMatch(false);
return List.of(
new HeaderMethodArgumentResolver(null, null),
new HeadersMethodArgumentResolver(),
new NotificationSubjectArgumentResolver(),
new AcknowledgmentHandlerMethodArgumentResolver(ACKNOWLEDGMENT),
new VisibilityHandlerMethodArgumentResolver(VISIBILITY),
new PayloadArgumentResolver(messageConverter));
}
}
I would expect to have a way to define a custom argument resolver but still have all the argument passed to the method once executed.

MapStruct: How to pass input object to expression?

In MapStruct version 1.1.0.Final, this was possible....
#Mappings({
#Mapping(target = "transaction.process.details", expression = "java(MappingHelper.mapDetails(request))"),
//more mappings
})
Response requestToResponse(Request request);
It was possible, since the mapDetails method was (by coincidence?) generated into the requestToResponse method. That's why request was not null.
Now, since 1.1.0.Final didn't work with Lombok, I had to upgrade to 1.2.0.CR2. With this version, the mapDetails will be generated into a separate method where request is not passed, so request is null within this method now and I get a NPE with the expression. (It's a sub-sub-method of requestToResponse now.)
Did I misuse the expression, so did it just work by coincidence, or does the new version has a bug? If no bug, how do I have to pass the request instance to the expression properly?
You were / are misusing the expression. What you need to do is to map your target to your source parameter.
#Mapper(uses = { MappingHelper.class })
public interface MyMapper {
#Mappings({
#Mapping(target = "transaction.process.details", source = "request"),
//more mappings
})
Response requestToResponse(Request request);
}
MapStruct then should create intermediary methods and use the MappingHelper and invoke the mapDetails method. In case you have multiple methods that map from Request to whatever type details are then you are going to need to used qualified mappings (see more here in the documentation).
It will look something like:
public class MappingHelper {
#Named("mapDetails") // or the better type safe one with the meta annotation #Qualifier
public static String mapDetails(Request request);
}
And your mapping will look like:
#Mapper(uses = { MappingHelper.class })
public interface MyMapper {
#Mappings({
#Mapping(target = "transaction.process.details", source = "request", qualifiedByName = "mapDetails"), //or better with the meta annotation #Qualifier qualifiedBy
//more mappings
})
Response requestToResponse(Request request);
}

vertx 2: vertx.eventBus().send(ClassName.ADDRESS, ....) why does it init a new class?

I work on a project based on Vertx the following line:
vertx.eventBus().send(MyClass.ADDRESS, requestBody, new Handler<Message<Object>>() {
....
}
public class MyClass implements Handler<Message<JsonObject>> {
public static final String ADDRESS = "coupons.api.manager";
...
#Override
public void handle(Message<JsonObject> msg) {
...
}
}
Whereas MyClass.ADDRESS is a static field of type string in the class MyClass, I found out that the line vertx.eventBus(...) creates an object of MyClass and then runs the handle() function.
My question is why? MyClass.ADDRESS is a string, and a static one. How does vertx "know" that it has to create an object from a class that this string is an attribute of?
I looked at the documentation of the send() function: http://vertx.io/docs/apidocs/io/vertx/core/eventbus/EventBus.html#send-java.lang.String-java.lang.Object-io.vertx.core.eventbus.DeliveryOptions-io.vertx.core.Handler-
and it says that the first argument in the function is "the address to send it to". OK. But, who said that the address means instantiating this class?
I made a small research, and yes. Vertx, behind the curtains, connects all the classes that implement Handler> to the string value they have in the attribute ClassName.ADDRESS.
When the statement:
vertx.eventBus().send(MyClass.ADDRESS, requestBody, new Handler<Message<Object>>() {
....
}
is invoked, a new thread is created and runs the handle method in the class MyClass.

Using function result inside expression function used by a predicate

I am trying to use predicateBuilder with next expression definition but I always got the message
"LINQ to Entities does not recognize the method 'puedeConsultar' method, and this method cannot be translated into a store expression."
I think i understand more less this problem, but i don´t know how to solve it.
private static readonly IDictionary<int, List<string>> permisosAccesoSolicitudesEstado = new Dictionary<int, List<string>>(){{0, new List<string>(){"A"}}, {1, new List<string>(){"B"}}};
private static bool esPermisoConcedido(List<string> usuariosPermitidos, string erfilUsuario)
{
return usuariosPermitidos.Any(x => x.Equals(perfilUsuario) || perfilUsuario.StartsWith(x + "|") || perfilUsuario.EndsWith("|" + x));
}
public static bool puedeConsultar(int estadoActual, string perfilUsuario)
{
List<string> usuariosPermitidos = permisosAccesoSolicitudesEstado[estadoActual];
return esPermisoConcedido(usuariosPermitidos, perfilUsuario);
}
public static bool puedeConsultar(string estadoActual, string tipoUsuario)
{
return puedeConsultar(Convert.ToInt32(estadoActual), tipoUsuario);
}
public Expression<Func<Solicitud, Boolean>> predicadoEstadoCorrectoSolicitud(string perfil)
{
return x=> EstadosSolicitud.puedeConsultar(x.estado, perfil);
}
//Instantiated by reflection, this works fine
MethodInfo method = .....
Expression<Func<T, bool>> resultado = ConstructorPredicados.True<T>();
resultado = ConstructorPredicados.And(resultado, method);
objectSet.Where(resultado).ToList();
Note:
ConstructorPredicados is based in Monty´s Gush "A universal PredicateBuilder" on http://petemontgomery.wordpress.com/2011/02/10/a-universal-predicatebuilder/
Thanks in advance
You cannot do that. Your puedeConsultar is .NET function. You cannot execute .NET functions in Linq-to-entities query. When you use method in Linq-to-entities you can use only methods which has direct mapping to SQL. It means that method in the query is only placeholder which is translated to execution of some SQL function. There is set of predefined method mappings called cannonical functions and you can map your own SQL function when using EDMX but in your case you will most probably have to first load data to application by using ToList and after that execute predicadoEstadoCorrectoSolicitud on materialized result.