Implicit arguments passing between microservices
There is an option to pass some additional arguments not by method call and it's arguments. There is special interface called JLupinInputParameterVariablesProducer
which can be implemented to pass some additional parameters. Let's see example to show what it's all about.
Native microservice interface
public interface DigestService {
MyDigest getMD5DigestWithParameters(String name, String surname) throws Throwable;
}
Native microservice implementation
@Service("digestService")
public class DigestServiceImpl implements DigestService {
private final Logger logger = LoggerFactory.getLogger(DigestServiceImpl.class);
@Override
public MyDigest getMD5DigestWithParameters(String name, String surname) throws Throwable {
final JLupinInputParameter jLupinInputParameter = JLupinUtil.getJLupinServiceContext().getJLupinInputParameter();
final Object contextObject = jLupinInputParameter.getContextObject();
final MyDigest myDigest = new MyDigest();
myDigest.setDigest(JLupinSecurityUtil.getMD5DigestAsHexString(
name + "|" + surname) + " toString() from contextObject=" + contextObject.toString()
);
return myDigest;
}
As you can see from call context you can get JLupinInputParameter
object which contains additional parameters. In this example contextObject
is retrieved. But the question is how to set them by the calling microservice. Let's move to the servlet microservice which will call our service.
Servlet microservice configuration
Generate standard beans for configuration with native microservice. Below you can see implementation which produces implicit parameters for remote calls.
public class MicroserviceApplicationConfiguration {
@Auto wired
private HttpSession httpSession;
@Bean
public JLupinDelegator getJLupinDelegator() {
return JLupinClientUtil.generateInnerMicroserviceLoadBalancerDelegator(PortType.JLRMC);
}
@Bean(name = "digestServiceWithParameterProducer")
public DigestService getDigestServiceWithParameterProducer() {
final JLupinProxyObjectProducer jLupinProxyObjectProducer = JLupinClientUtil.generateRemote(
getJLupinDelegator(),
"sampleNativeMicroservice",
"digestService",
DigestService.class,
new JLupinInputParameterVariablesProducer() {
@Override
public String produceSessionId() {
return httpSession.getId();
}
@Override
public String produceRequestId() {
return "requestId";
}
@Override
public String produceClientApplicationName() {
return "clientApplicationName";
}
@Override
public String produceIp() {
return "192.168.0.1";
}
@Override
public Locale produceLocale() {
return "en";
}
@Override
public String produceUser() {
return "user";
}
@Override
public String[] producePrivilegesName() {
return new String[]{ "USER" };
}
@Override
public Object produceTransactionObject() {
return "transactionObject";
}
@Override
public Object produceContextObject() {
return new String("session id from spring controller:" + httpSession.getId());
}
@Override
public String produceMonitoringId() {
return "monitoringId";
}
}
);
return jLupinProxyObjectProducer.produceObject(DigestService.class);
}
}
Above only context object is generated. It can be any object, including lists, etc. The only requirement is that this object must serializable. Of course you can implement every method above to set parameters you want.
Servlet controller implementation
Service call looks same as without JLupinInputParameterVariablesProducer
. You just call your microservice method. Methods of JLupinInputParameterVariablesProducer
are executed for each method call by JLupin library.
@RestController
public class DigestController {
private final Logger logger = LoggerFactory.getLogger(DigestController.class);
@Autowired
@Qualifier("digestServiceWithParameterProducer")
private DigestService digestServiceWithParameters;
@PostMapping("/digestRemoteWithParameters")
public DigestResponse digestRemoteWithParameters(@RequestBody DigestRequest digestRequest) throws Throwable {
final MyDigest myDigest = digestServiceWithParameters.getMD5DigestWithParameters(digestRequest.getName(), digestRequest.getSurname());
return new DigestResponse(myDigest.getDigest());
}
}
Flow description
Let's sum up what is happening when you make your request. Firstly DigestController
is executing it's method digestRemoteWithParameters
. Inside method generated proxy (with JLupinInputParameterVariablesProducer
) is called. So JLupin library prepares serialized object to send to native microservice. It is calling each method of JLupinInputParameterVariablesProducer
and put results into this prepared serialized object. Then object is send to your native microservice. Next step is to handle method invocation by native microservice. It receives serialized object, deserialize it and puts every variable inside it's call context. Then checks what method and what service is needed to execute. In our example it is digestService
and method getMD5DigestWithParameters
. So it is called by JLupin (remember that we are already on native microservice side of communication). Because received implicit parameters were set in call context they can be retrieved from JLupinInputParameter
. Here we take context object and passes it into MyDigest
with name
and surname
. So method execution is done. It's result is serialized and sent back to servlet microservice. On servlet microservice side generated remote deserializes received result and returns it. Result is saved to variable myDigest
and returned from controller.