How to get HttpServletRequest in Liferay WebService - web-services

Hi I have a webService that is generated from buildServices of Liferay..
the method looks like this
public User getUserTest(long userId) {
User u = null;
try {
Token token = OAuthFactoryUtil.createToken("sasa", "sdad");
} catch (OAuthException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
try {
u = UserLocalServiceUtil.getUser(userId);
System.out.println("xx user " + u.getScreenName());
} catch (Exception e) {
System.out.println(" Exception ************* " + e.toString());
}
return u;
}
the parameters in this ws would be this :
http://localhost:8080/demo-portlet/api/json?serviceClassName=com.sample.portlet.library.service.BookServiceUtil&serviceMethodName=getUserTest&userId=10195&serviceParameters=[userId]
having userId as a parameter..
How would you pass a parameter if you need HttpServletRequest.. my method would look like this
public User getUserTest(HttpServletRequest httpRequest) {
User u = null;
try {
String version = httpRequest.getHeader("X-PHM-APP-VERSION");
Token token = OAuthFactoryUtil.createToken("sasa", "sdad");
} catch (OAuthException e1) {
e1.printStackTrace();
}
try {
String authorization = httpRequest.getHeader("Authorization");
u = UserLocalServiceUtil.getUser(Long.valueOf(authorization));
System.out.println("authorization --> " + authorization);
System.out.println("xx user " + u.getScreenName());
} catch (Exception e) {
System.out.println(" Exception ************* " + e.toString());
}
return u;
}
I need the HttpServletRequest to get the parameters from header, instead of passing through url. Is there a better way to get parameters from header? thanks for your help

I think webservice layer is normally at a later stage where in you would never pass request. Ideally what you would do is pass header parameter to the webservice instead of request

In Liferay, you will get HttpServletRequest from the PortletRequest. Please use com.liferay.portal.util.PortalUtil class.
There are 2 methods in it. getHttpServletRequest() and getOriginalServletRequest(), you will get the both core level http request from these methods.

Related

How can I prevent a method call when JUnit testing with Mockito?

For the life of me, I can't seem to figure out how to prevent the method I'm testing from calling a method in another class.
Here is my test class:
#ExtendWith(MockitoExtension.class)
class QueryHandlerTest {
#InjectMocks
QueryHandler queryHandler;
#Mock
ResponseBuilder responseBuilder;
#BeforeEach
void setUp() {
MockitoAnnotations.openMocks(this);
}
#Test
void TC5() {
doThrow(AddMessageResponseException.class).when(responseBuilder).addMessageResponse(isA(Boolean.class), isA(Boolean.class));
assertThrows(AddMessageResponseException.class, ()-> queryHandler.addMessage("Hello",true));
}
}
Here is the method that I'm testing:
public void addMessage(String message, boolean lengthExceedsLimit) {
boolean messageAdded;
if (checkIfJarExists()) {
if (!lengthExceedsLimit) {
// attempt to add the message to the jar
messageAdded = addMessageQuery(new Message(event.getMessageAuthor().getIdAsString(), message));
} else {
messageAdded = false;
}
} else {
messageAdded = false;
}
responseBuilder.addMessageResponse(messageAdded, lengthExceedsLimit);
if (messageAdded) {
// check to see if the jar's message limit has been reached; if so, perform opening ceremony
if (checkMessageLimit()) {
responseBuilder.performOpeningEvent(currentJar);
deleteJarQuery(this.serverId);
}
}
}
And here is the method that it's calling:
public void addMessageResponse(boolean messageAdded, boolean lengthExceedsLimit){
if (lengthExceedsLimit) {
event.getChannel().sendMessage("I'm sorry, your message is too long. Please limit your message " +
"to 250 characters or less.");
} else if(messageAdded){
String nickname = getNickname();
event.getChannel().sendMessage("Thanks, " + nickname + "! Your message has " +
"been added to the jar!");
} else {
event.getChannel().sendMessage("Sorry, it looks like a jar has not been set up for your server. " +
"If you're a server admin, you can create a jar! " +
"Please use '!tiko help' to see a list of my commands.");
}
}
When I run the test, I get this output:
org.opentest4j.AssertionFailedError: Unexpected exception type thrown,
Expected :class com.tikoJar.exceptions.AddMessageResponseException
Actual :class java.lang.NullPointerException
<Click to see difference>
...
Caused by: java.lang.NullPointerException: Cannot invoke "org.javacord.api.entity.channel.TextChannel.sendMessage(String)" because the return value of "org.javacord.api.event.message.MessageCreateEvent.getChannel()" is null
at com.tikoJar.DTO.ResponseBuilder.addMessageResponse(ResponseBuilder.java:35)
at com.tikoJar.DTO.QueryHandler.addMessage(QueryHandler.java:74)
at com.tikoJar.DTO.QueryHandlerTest.lambda$TC5$0(QueryHandlerTest.java:68)
at org.junit.jupiter.api.AssertThrows.assertThrows(AssertThrows.java:53)
... 73 more
As you can see, the method I'm testing is calling and running the addMessageResponse() method in the ResponseBuilder class, even though I specified in my test that a custom exception should be thrown when attempting to call that method.
I've also tried specifying:
doNothing().when(responseBuilder).addMessageResponse(isA(Boolean.class), isA(Boolean.class));
... but the method still gets called and run. What can I do here?

Response not coming back from one service to another service - microservices

I am facing strange issue where response as string not coming back from one service to another service. we have created microservices where one service is calling another service. i can see response printed in logs . after that line immediately i am returning that response but its coming back as null.
I created similar method with same code and it works fine. I have put code for calling service and service method from which i am returning response.
controller:
#RequestMapping(value = "/test/save", method = RequestMethod.POST)
#ResponseBody
public String save(#RequestBody Calculation calculation,
HttpServletRequest request) {
logger.info("In .save");
String result = "false";
try {
result = CalService.save(calculation);
logger.info("Response from service is :" + result);
} catch (Exception e) {
logger.error("Exception occured in save:", e);
}
return result;
}
method call client :
public String saveCal(Calculation calculation) {
String result = null;
try {
logger.info("In save");
MultiValueMap<String, String> headers = new LinkedMultiValueMap<String, String>();
headers.add("REMOTE_USER", "test");
HttpEntity<Calculation> request = new HttpEntity<Calculation>(Calculation, headers);
RestTemplate template = new RestTemplate();
template.getMessageConverters().add(new MappingJackson2HttpMessageConverter());
result = template.postForObject(url+"/test/save", request, String.class);
} catch (Exception e) {
logger.error("Exception occured in SaveMddMd", e);
result = "fail";
}
logger.info("Save"+result);
return result;
}
result returned is success or failure.
I can see result printed in controller as success but when it comes back to client it prints as null. I created exact same method with different signature which returns result as success. we are using microservices here.
Jordan

Issue with a WS verifier method when migrating from Play 2.4 to Play 2.5

I have a method I need to refactor, as F.Promise has been deprecated in Play 2.5. It's pretty readable actually. It sends a request and authenticates via a custom security token and returns true if the response is 200.
public boolean verify(final String xSassToken){
WSRequest request = WS.url(mdVerifyXSassTokenURL)
.setHeader("X-SASS", xSassToken)
.setMethod("GET");
final F.Promise<WSResponse> responsePromise = request.execute();
try {
final WSResponse response = responsePromise.get(10000);
int status = response.getStatus();
if(status == 200 ) { //ok
return true;
}
} catch (Exception e) {
return false;
}
return false;
}
First thing I had to do was change this line:
final F.Promise<WSResponse> responsePromise = request.execute();
To this:
final CompletionStage<WSResponse> responsePromise = request.execute();
However, CompletionStage(T) doesn't have an equivalent get() method so I'm not sure the quickest and easiest way to get a WSResponse that I can verify the status of.
Yes, it does not. At least not directly.
What you are doing is "wrong" in the context of PlayFramework. get is a blocking call and you should avoid blocking as much as possible. That is why WS offers a non blocking API and a way to handle asynchronous results. So, first, you should probably rewrite your verify code to be async:
public CompletionStage<Boolean> verify(final String xSassToken) {
return WS.url(mdVerifyXSassTokenURL)
.setHeader("X-SASS", xSassToken)
.setMethod("GET")
.execute()
.thenApply(response -> response.getStatus() == Http.Status.OK);
}
Notice how I'm using thenApply to return a new a java.util.concurrent.CompletionStage instead of a plain boolean. That means that the code calling verify can also do the same. Per instance, an action at your controller can do something like this:
public class MyController extends Controller {
public CompletionStage<Result> action() {
return verify("whatever").thenApply(success -> {
if (success) return ok("successful request");
else return badRequest("xSassToken was not valid");
});
}
public CompletionStage<Boolean> verify(final String xSassToken) { ... }
}
This way your application will be able to handle a bigger workload without hanging.
Edit:
Since you have to maintain compatibility, this is what I would do to both evolve the design and also to keep code compatible while migrating:
/**
* #param xSassToken the token to be validated
* #return if the token is valid or not
*
* #deprecated Will be removed. Use {#link #verifyToken(String)} instead since it is non blocking.
*/
#Deprecated
public boolean verify(final String xSassToken) {
try {
return verifyToken(xSassToken).toCompletableFuture().get(10, TimeUnit.SECONDS);
} catch (Exception e) {
return false;
}
}
public CompletionStage<Boolean> verifyToken(final String xSassToken) {
return WS.url(mdVerifyXSassTokenURL)
.setHeader("X-SASS", xSassToken)
.setMethod("GET")
.execute()
.thenApply(response -> response.getStatus() == Http.Status.OK);
}
Basically, deprecate the old verify method and suggest users to migrate to new one.

How to verify for counter signed XML document?

How to verify the use library Xades4j for counter signed xml document.
Iam getting the following error when verifying with Xades4j :
xades4j.verification.CounterSignatureSigValueRefException:
Verification failed for property 'CounterSignature': the counter
signature doesn't reference the SignatureValue element of the
countersigned signature at
xades4j.verification.CounterSignatureVerifier.verify(CounterSignatureVerifier.java:75)
at
xades4j.verification.CounterSignatureVerifier.verify(CounterSignatureVerifier.java:37)
at
xades4j.verification.GenericDOMDataVerifier.verify(GenericDOMDataVerifier.java:65)
at
xades4j.verification.GenericDOMDataVerifier.verify(GenericDOMDataVerifier.java:30)
at
xades4j.verification.QualifyingPropertiesVerifierImpl.verifyProperties(QualifyingPropertiesVerifierImpl.java:59)
at
xades4j.verification.XadesVerifierImpl.verify(XadesVerifierImpl.java:187)
at
com.fit.einvoice.ingcountersigner.service.xades.XadesVerifyOperation.verifySignature(XadesVerifyOperation.java:92)
at
com.fit.einvoice.ingcountersigner.service.xades.XadesVerifyOperation.verifySignature(XadesVerifyOperation.java:87)
at
com.fit.einvoice.ingcountersigner.service.xades.XadesVerifyOperation.verifySignature(XadesVerifyOperation.java:64)
My validation function :
static void checkSigned(File file) {
InputStream inputStream = null;
try {
inputStream = new FileInputStream(file);
XadesVerifyOperation verifyOperation = new XadesVerifyOperation();
ArrayList<XadesVerificationResults> results = verifyOperation.verifySignature(inputStream);
System.out.println("results size: " + results.size());
for (XadesVerificationResults result : results) {
System.out.println(result.SigningCertificate.getIssuerDN());
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
inputStream.close();
} catch (IOException ex) {
}
}
}
EDIT:
My counter signed function :
public void CounterSign() throws TransformerFactoryConfigurationError, Exception {
Document doc = SignatureServicesBase.getDocument(_inputStream);
Element sigElem = (Element) doc.getElementsByTagNameNS(Constants.SignatureSpecNS, Constants._TAG_SIGNATURE).item(0);
System.out.println(sigElem.getNodeName());
org.apache.xml.security.Init.init();
XMLSignature xmlSig = new XMLSignature(sigElem, doc.getBaseURI());
//Create counter signer
XadesBesSigningProfile signingProfile = new XadesBesSigningProfile(new Pkcs11KeyingDataProvider(_certInfo));
signingProfile.withAlgorithmsProvider(Sha1AlgProvider.class);
signingProfile.withBasicSignatureOptionsProvider(new MyBasicSignatureOptionsProvider(true, true, false));
final XadesSigner counterSigner = signingProfile.newSigner();
//Extend with counter signature
XadesFormatExtenderProfile extenderProfile = new XadesFormatExtenderProfile();
XadesSignatureFormatExtender extender = extenderProfile.getFormatExtender();
List unsignedProps = Arrays.asList(new CounterSignatureProperty(counterSigner));
extender.enrichSignature(xmlSig, new UnsignedProperties(unsignedProps));
SignatureServicesBase.outputDocument(doc, _outStream);
if (!_isStream) {
_inputStream.close();
_outStream.close();
}
}
I'm not sure I completely understood your question. If you're asking how to verify a counter signature property, it is already done as part of the verification of the "main" signature. Please note:
The same XadesVerifier is used for both the main signature and the counter signature.
If the validation succeeds, a property of type CounterSignatureProperty is added to the result.
You can access the property through the verification result of the main signature
XAdESVerificationResult res = ...;
CounterSignatureProperty p = res.getPropertiesFilter().getOfType(CounterSignatureProperty.class);
EDIT:
The message says everything: the counter signature is probably invalid. By definition, a counter signature must include a reference to the countersigned SignatureValue element.
Can you lookup the CounterSignature element on the original XML document and post it here?

How to send additional fields to soap handler along with soapMessage?

I am logging RequestXML for a webservice client using SoapHandler as follows
public boolean handleMessage(SOAPMessageContext smc) {
logToSystemOut(smc);
return true;
}
private void logToSystemOut(SOAPMessageContext smc) {
Boolean outboundProperty = (Boolean)
smc.get (MessageContext.MESSAGE_OUTBOUND_PROPERTY);
if (outboundProperty.booleanValue()) {
out.println("\nOutbound message:");
} else {
out.println("\nInbound message:");
}
SOAPMessage message = smc.getMessage();
try {
message.writeTo(out);
out.println("");
} catch (Exception e) {
out.println("Exception in handler: " + e);
}
}
Got a new requirenment to add this xml to DB along with some extra values(which are not present in the xml). Is there any way I can pass few additional fields to above soap handler (in handleMessage method)?
Please note that changing the xml/WSDL or adding this to SOAP message header is not an option for me as it is owned by other interface. Any other solution?
Thanks!
You can cast your service class to a class of type "BindingProvider". In this form you can use it to assign it objects which you can access later from your SOAPHandler. Another useful usage is that you also can change the endPoint URL this way.
Before calling the service you do:
MySoapServicePortType service = new MySoapService().getMySoapServicePort();
BindingProvider bp = (BindingProvider)service;
MyTransferObject t = new MyTransferObject();
bp.getRequestContext().put("myTransferObject", t);
TypeResponse response = service.doRequest();
SOAPMessage message = t.getRequestMessage(message);
From your logging function you do:
private void logToSystemOut(SOAPMessageContext smc) {
...
MyTransferObject t = (MyTransferObject) messageContext.get("myTransferObject");
if (outboundProperty.booleanValue())
t.setRequestMessage(message);
else
t.setResponseMessage(message);
...
}