0

I'm dealing with the problem with passing parameteres to web-service.

I have created web-service which works OK for the case fromLanguage = "eng"

But, when I test service through Glassfish console and send fromLanguage = "bos" I don't get appropriate result.

package pckgTranslator;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;

@Path("/MyRestService/{wordToTranslate},{fromLanguage},{toLanguage}")
public class clsTranslate {
@GET
public String doGet(@PathParam("wordToTranslate") String wordToTranslate, 
        @PathParam("fromLanguage") String fromLanguage, @PathParam("toLanguage")  String toLanguage) 
        throws Exception{
    Translator translator = new Translator();
    return translator.getTranslation(wordToTranslate,fromLanguage, toLanguage);        
}

}

This is XML fajl which I try to parse:

<?xml version="1.0" encoding="utf-8" ?>
<gloss>
    <word id="001">
        <eng>ball</eng>
        <bos>lopta</bos>
    </word>
    <word id="002">
        <eng>house</eng>
        <bos>kuca</bos>
    </word>
    <word id="003">
        <eng>game</eng>
        <bos>igra</bos>
    </word>
</gloss>

And this is the class which I'm using for parsing XML.

package pckgTranslator;
import java.io.IOException;
import java.io.InputStream;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

public class Translator {

String translation = null;

String getTranslation(String wordForTransl, String fromLanguage, String toLanguage)
        throws ParserConfigurationException, SAXException, IOException, XPathExpressionException {

    //fromLanguage = "eng";
    //toLanguage = "bos";

    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
    factory.setNamespaceAware(true);

    DocumentBuilder builder = factory.newDocumentBuilder();
    InputStream is = Translator.class.getResourceAsStream("/resource/glossary.xml");
    Document doc = builder.parse(new InputSource(is));

    XPathFactory xpathfactory = XPathFactory.newInstance();
    XPath xpath = xpathfactory.newXPath();

    //XPathExpression expr = null; //xpath.compile("//word[eng='house']/bos/text()");
    XPathExpression expr = xpath.compile("//word['" + wordForTransl + "'='" + wordForTransl + "']/bos/text()");
    if (fromLanguage == "eng") {
        expr = xpath.compile("//word[eng='" + wordForTransl + "']/bos/text()");
    } else if (fromLanguage == "bos") {
        expr = xpath.compile("//word[bos='" + wordForTransl + "']/eng/text()");

    }

    Object result = expr.evaluate(doc, XPathConstants.NODESET);
    NodeList nodes = (NodeList) result;
    for (int i = 0; i < nodes.getLength(); i++) {
        //System.out.println(nodes.item(i).getNodeValue());
        translation = nodes.item(i).getNodeValue();
    }
    //return nodes.item(i).getNodeValue();
    if (translation != null) {
        return translation;
    } else {
        return "We are sorry, there is no translation for this word!";
        }
    }
}

It seems to me that something is wrong with the parameters fromLanguage and toLanguage, but I can't realize what exactly. Thanks in advance.

5
  • Seems you have hardcoded fromLanguage and toLanguage variables to eng and bos at the beginning of getTranslation() method. Remove these assignments and check. Commented Aug 10, 2019 at 7:51
  • I see another issue in @Path. Why do you have comma separated path params? Commented Aug 10, 2019 at 9:36
  • What is appropriate way to separate parameters? I couldn't find the another option. Commented Aug 10, 2019 at 9:40
  • Separate with / instead of ,. Modified the answer. Commented Aug 10, 2019 at 9:42
  • please see the updated answer. If you need to pass multiple parameters, either use multiple @PathParam separated by / or use @QueryParam. After making this change of you still face issues, please log or print the input values i in doGet() method to understand what exactly you are getting. Commented Aug 10, 2019 at 9:52

1 Answer 1

1

As I mentioned in the comment, you have hardcoded fromLanguage and toLanguage variables to eng and bos at the beginning of getTranslation() method. Due to this, the fromLanguage and 'toLangugaevalues passed togetTranslation()` method are lost.

Secondly, instead of separating @PathParm by , separate those by /. It will look like:

@Path("/MyRestService/{wordToTranslate}/{fromLanguage}/{toLanguage}")
@GET
public String doGet(@PathParam("wordToTranslate") String wordToTranslate, 
@PathParam("fromLanguage") String fromLanguage, @PathParam("toLanguage")  String toLanguage) throws Exception

Invocation: curl -X GET http://localhost:8080/MyRestService/x/y/z

Alternatively use @QueryParam. In that case your path would be:

@Path("/MyRestService")
public String doGet(@QueryParam("wordToTranslate") String wordToTranslate, 
@QueryParam("fromLanguage") String fromLanguage, @QueryParam("toLanguage")  String toLanguage) throws Exception

Invocation: curl -X GET http://localhost:8080/MyRestService?wordToTranslate=x&fromLanguage=y&toLanguage=z

Remove or comment the below lines in getTranslation() method:

fromLanguage = "eng";
toLanguage = "bos";

Note: To fix your issue the above solution is sufficient. However, to make you code better please see the below suggestions. In addition to the above I see two more issues:

  • You are storing translated value in translation instance variable. In case you are using the same Translator object (singleton instance) and the current translation fails, getTranslation() will return the previously translated value.
  • Why are you initializing expr with the below?
   XPathExpression expr = xpath.compile("//word['" + wordForTransl + "'='" + wordForTransl + "']/bos/text()");
  • Lastly, every time you are calling getTranslation() the XML is being parsed. Instead, parse it once in init() method and then use it in getTranslation() method.

I have modified your Translator class based on the above points:

package org.openapex.samples.misc.parse.xml;

import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.*;
import java.io.IOException;
import java.io.InputStream;

public class ParseXMLAndTranslate {
    public static void main(String[] args) throws Exception{
        Translator translator = new Translator();
        translator.init();
        System.out.println(translator.getTranslation("house","eng", "bos"));
        System.out.println(translator.getTranslation("igra","bos", "eng"));
    }

    private static class Translator {
        //String translation = null;
        private Document doc;
        public void init() throws ParserConfigurationException, SAXException, IOException{
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            factory.setNamespaceAware(true);
            DocumentBuilder builder = factory.newDocumentBuilder();
            InputStream is = Translator.class.getResourceAsStream("/resource/glossary.xml");
            this.doc = builder.parse(new InputSource(is));
        }

        String getTranslation(String wordForTransl, String fromLanguage, String toLanguage)
                throws XPathExpressionException {
            //fromLanguage = "eng";
            //toLanguage = "bos";
            XPathFactory xpathfactory = XPathFactory.newInstance();
            XPath xpath = xpathfactory.newXPath();

            //XPathExpression expr = null; //xpath.compile("//word[eng='house']/bos/text()");
            //XPathExpression expr = xpath.compile("//word['" + wordForTransl + "'='" + wordForTransl + "']/bos/text()");
            XPathExpression expr = null;
            if (fromLanguage == "eng") {
                expr = xpath.compile("//word[eng='" + wordForTransl + "']/bos/text()");
            } else if (fromLanguage == "bos") {
                expr = xpath.compile("//word[bos='" + wordForTransl + "']/eng/text()");
            }

            Object result = expr.evaluate(doc, XPathConstants.NODESET);
            NodeList nodes = (NodeList) result;
            String translation = null;
            /*for (int i = 0; i < nodes.getLength(); i++) {
                //System.out.println(nodes.item(i).getNodeValue());
                translation = nodes.item(i).getNodeValue();
            }*/
            if(nodes.getLength() > 0){
                translation = nodes.item(0).getNodeValue();
            }
            //return nodes.item(i).getNodeValue();
            if (translation != null) {
                return translation;
            } else {
                return "We are sorry, there is no translation for this word!";
            }
        }
    }
}

Here is the output:

kuca
game
Sign up to request clarification or add additional context in comments.

6 Comments

Thank you very much for help. I think that I understood your suggestions, but don't understand for what the "public class ParseXMLAndTranslate stands" class stands for. PS - I edited original class Translator, commented two lines fromLanguage and toLanguage, but the problem still persists.
ParseXMLAndTranslate class is to test your Translator. You may ignore this. Did you modify the separator , to / in @Path annotation? Also, move the @Path annotation to doGet() method from the class level. Did you print on console or log what values you are receiving in doGet() method?
Thanks for help and patiente. I will try to implement it now. Sorry, I'm novice in Java.
@Adnan No problem. Please try to change the @Path declaration as suggested in the answer. If your issue is not resolved please let me know.
I deeply studied your code. I created completely new Java project in Netbeans (Java DESKTOP app) and it really great works. But, for some reason, the same code doesn't work when I try to implement REST service (via WEB app in Netbeans). Especially when I try to put annotations inside the clsTranslate class like this i.postimg.cc/qvqvkvKX/cls-Translate.png - in such case REST service is not available for testing in Glassfish console. i.postimg.cc/50VJF4Xr/test-Web-Service.png
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.