Using Metro, adding a MTOMFeature to client side causes a MIMEParsingException, why? - java

We have an MTOM-enabled web service that is published with Grails and the Metro 1.0.2 plugin:
#MTOM
#WebService(targetNamespace="http://com.domain")
class TestService {
#WebMethod
int uploadFile(#XmlMimeType("application/octet-stream")DataHandler data) {
data.dataSource.inputStream.eachLine {
println "reading: -> ${it}"
}
return 0
}
}
Following this tutorial, we set up a Java test-client that looks like this
public class Client {
public static void main(String[] argv) {
MTOMFeature feat = new MTOMFeature();
TestService service = new TestServiceService().getTestServicePort(feat);
Map<String, Object> ctxt = ((BindingProvider)service).getRequestContext();
ctxt.put(JAXWSProperties.HTTP_CLIENT_STREAMING_CHUNK_SIZE, 8192);
service.uploadFile(new DataHandler(new FileDataSource("c:/file.xml")));
}
}
When I run the client, I get the following error message:
Couldn't create SOAP message due to
exception:
org.jvnet.mimepull.MIMEParsingException:
Missing start boundary
However, when I don't add the MTOMFeature, and just do
TestService service = new TestServiceService().getTestServicePort(); the files gets uploaded ok. But as I understand it if MTOM is not enabled on both server and client side, the entire file will be kept in memory (and not streamed). So, my questions are
Why do we get that error?
If I don't add the MTOMFeature, will the file still be MTOM-transmitted?
I would be very grateful for any help/tips!

After some research and testing, the answers are:
The error is because grails adds its own filtering, including services. So, by excluding the services from being filtered like this static excludes = ["/services/*"] in UrlMappings.groovy, it works.
No. Without the MTOMFeature the file will just be treated as any other data in the request. That means being stored in the memory, thus causing problems for big files.

Related

Applications Credentials not avaliable in Google Cloud Vision API

I am trying to setup Google Cloud Vision API, I have defined a Application Credential Variable through CMD by using set GOOGLE_APPLICATION_CREDENTIALS PathToJSON however this still does not allow me to connect to Google Cloud Vision API for OCR.
I have also tried to set it manually through the windows UI, however still no luck, I created and defined a project in the Google Cloud page, and generated a credential key, when it asked me "Are you planning to use this API with App Engine or Compute Engine?", I selected No.
I am currently using Googles boilerplate code
public class DetectText {
public static void main(String args[])
{
try{
detectText();
}catch (IOException e)
{
e.printStackTrace();
}
}
public static void detectText() throws IOException {
// TODO(developer): Replace these variables before running the sample.
String filePath = "C:\\Users\\Programming\\Desktop\\TextDetection\\Capture.PNG";
detectText(filePath);
}
// Detects text in the specified image.
public static void detectText(String filePath) throws IOException {
List<AnnotateImageRequest> requests = new ArrayList<>();
ByteString imgBytes = ByteString.readFrom(new FileInputStream(filePath));
Image img = Image.newBuilder().setContent(imgBytes).build();
Feature feat = Feature.newBuilder().setType(Feature.Type.TEXT_DETECTION).build();
AnnotateImageRequest request =
AnnotateImageRequest.newBuilder().addFeatures(feat).setImage(img).build();
requests.add(request);
// Initialize client that will be used to send requests. This client only needs to be created
// once, and can be reused for multiple requests. After completing all of your requests, call
// the "close" method on the client to safely clean up any remaining background resources.
try (ImageAnnotatorClient client = ImageAnnotatorClient.create()) {
BatchAnnotateImagesResponse response = client.batchAnnotateImages(requests);
List<AnnotateImageResponse> responses = response.getResponsesList();
for (AnnotateImageResponse res : responses) {
if (res.hasError()) {
System.out.format("Error: %s%n", res.getError().getMessage());
return;
}
// For full list of available annotations, see http://g.co/cloud/vision/docs
for (EntityAnnotation annotation : res.getTextAnnotationsList()) {
System.out.format("Text: %s%n", annotation.getDescription());
System.out.format("Position : %s%n", annotation.getBoundingPoly());
}
}
}
}
static void authExplicit(String jsonPath) throws IOException {
}
}
I am not using a server or Google compute virtual machine.
Can someone please explain to me what the problem is, and how I would go about fixing it?
Stack Trace
java.io.IOException: The Application Default Credentials are not available. They are available if running in Google Compute Engine. Otherwise, the environment variable GOOGLE_APPLICATION_CREDENTIALS must be defined pointing to a file defining the credentials. See https://developers.google.com/accounts/docs/application-default-credentials for more information.
at com.google.auth.oauth2.DefaultCredentialsProvider.getDefaultCredentials(DefaultCredentialsProvider.java:134)
at com.google.auth.oauth2.GoogleCredentials.getApplicationDefault(GoogleCredentials.java:119)
at com.google.auth.oauth2.GoogleCredentials.getApplicationDefault(GoogleCredentials.java:91)
at com.google.api.gax.core.GoogleCredentialsProvider.getCredentials(GoogleCredentialsProvider.java:67)
at com.google.api.gax.rpc.ClientContext.create(ClientContext.java:142)
at com.google.cloud.vision.v1.stub.GrpcImageAnnotatorStub.create(GrpcImageAnnotatorStub.java:117)
at com.google.cloud.vision.v1.stub.ImageAnnotatorStubSettings.createStub(ImageAnnotatorStubSettings.java:156)
at com.google.cloud.vision.v1.ImageAnnotatorClient.<init>(ImageAnnotatorClient.java:136)
at com.google.cloud.vision.v1.ImageAnnotatorClient.create(ImageAnnotatorClient.java:117)
at com.google.cloud.vision.v1.ImageAnnotatorClient.create(ImageAnnotatorClient.java:108)
at DetectText.detectText(DetectText.java:54)
at DetectText.detectText(DetectText.java:36)
at DetectText.main(DetectText.java:25)
Based on your error message, it seems that the GOOGLE_APPLICATION_CREDENTIALS environment variable is not being found.
On one hand, before trying to run the text detection sample code, follow the steps outlined in the documentation in order to discard that any of them has been skipped.
On the other hand, if you are using an IDE such as IntelliJ or Eclipse, you have to set the environment variable GOOGLE_APPLICATION_CREDENTIALS global through Windows System Properties, so it can be used by the IDE. Nevertheless, when testing I had to close and reopen the IDE for the changes to take effect and the aforementioned error would not appear.
Additionally, there is also a way to specify the location of the JSON file within the code, as shown in this example. However, it is not advisable to put it that way, it is best to use the environment variables.

Hawkular And Vertx: Why the new installed Hawkular Metric Server does not receive any metrics?

my goal is to visualize vertx metrics - like for example the counts of messages, which are sent over eventbus and so on.
(please consider thath the following tools are all together on my localhost, nothing resides on separated machines)
Therefor I have used the Hawkular implementation of vertx: http://vertx.io/docs/vertx-hawkular-metrics/java/
First I installed CassandraDB with default settings:
http://www.planetcassandra.org/cassandra/
To build the Hawkular Metrics-alone Server I took an WildFly 10 and deployed the Metrics-warFile from here: https://github.com/hawkular/hawkular-metrics/releases/
When I now start the wildfly server I got under the url :http://localhost:8080/hawkular/metrics the starter screen with "Metrics Service started".
Until now all seem to be running fine....
Now I want to insert metric data - for that i programmed an short verticle with HawkularAPI:
public class Sender extends AbstractVerticle {
public static void main(String[] args) {
VertxOptions options = new VertxOptions();
VertxHawkularOptions hawkularOptions = new VertxHawkularOptions().setEnabled(true).setTenant("hawkular").setHost("localhost").setPort(8080);
options.setMetricsOptions(hawkularOptions);
Vertx.clusteredVertx(options, res -> {
Vertx vertx = res.result();
vertx.deployVerticle(new Sender());
});
}
#Override
public void start() throws Exception {
vertx.setPeriodic(1500, id -> {
vertx.eventBus().send("test", "testSend");
System.out.println("SEND!");
});
}
}
But nothing happens - have i missed something? My opinion was that I perhaps can see some charts for example by hitting :http://localhost:8080/hawkular/metrics /counter/vertx etc....instead of graphics I get following ErrorMessage:
{"errorMsg":"Tenant is not specified. Use 'Hawkular-Tenant' header."}
Hawkular Metrics does not provide charts. You need to start a graphical client like Grafana.
See http://www.hawkular.org/hawkular-clients/grafana/docs/quickstart-guide/

JAXRS Server check status

I have created a JAXRS SERVER for some web services. The server is working just fine, but I need to add a new feature so that I can check the server status at any time. So if the server is up I should return a message like running,and if is down a message like down.
My implementation so far:
public class Server
{
public static void main( final String[] args )
{
final JAXRSServerFactoryBean serverFactory = new JAXRSServerFactoryBean();
final SubscriptionService subscriptionService =
new SubscriptionService( SubscriptionRepo.getRepo() );
final SystemService systemservice = new SystemService();
serverFactory.setResourceProvider(new SingletonResourceProvider(subscriptionService));
serverFactory.setResourceProvider(new SingletonResourceProvider(systemservice));
serverFactory.setAddress( "http://localhost:8888" );
serverFactory.setProvider( JacksonJsonProvider.class );
serverFactory.create();
}
}
I have also created a service class where I want to get the status:
public class SystemService
{
#GET
#Path("/systemstatus")
public Response getSystemStatus()
{
return Response.status( Status.OK.getStatusCode() );
}
}
I really have no idea how can I return a status if the system is running or not.
Can anyone help me with some ideas on how to check the server status?
Your quest kind of collapses on itself when you consider that you're trying to get a response from a web service, that's deployed on a non-responsive web server. How exactly do you envisage your web service getting the word out (by way of a coherent HTTP status, no less), that it's not reachable? How are you even going to get to it in the first place? When the container is down, your service is not in a position to return any meaningful message to the client
Stick to time-tested exception handling in the various flavours of the connection-related SocketException and possibly the HttpRetryException, in some cases. That's all you're going to get when your server is not up: some variety of SocketException. Your REST service has no power here.

Run out of ports calling my webservice from an android app

I have an android app and a C# web service
I am hosting my web service on IIS Express - nothing fancy just set up the directories.
My android app go to the web service gets the data and then displays it on the screen and repeats this as fast as it can go.
After a while my android app will throw the following exception:
"SoapFault - faultcode: 'soap:Server' faultstring: 'Server was unable to process request. ---> No ports available in the range 10101 to 11100' faultactor: 'null' detail: org.kxml2.kdom.Node#41bdf340"
I have Googled around a bit and have not found anything that will help me.
I ran CurrPorts to watch the ports and it looks like every time the app calls the web service it is using a different port.
They all use port 80 but different remote ports.
The exception is being thrown on the following line of code
"SoapPrimitive response = (SoapPrimitive) _envelope.getResponse();"
If I run IISReset the app will go back to getting data again until sometime thereafter to get the exception mentioned above.
Here is the code for my web service which is just returning a comma separated string (it will do something more interesting just trying to get this working)
Web service code
[WebMethod]
public string GetDefaultResults()
{
return "100,1,0,125.987,124.993,117.904,116.038";
}
Here is the code that my android app uses to call the web service.
I create a new thread and have it call this method then get the string value split it on ',' then put it in a few different TextViews
public class WebService implements Runnable{
private static String NAMESPACE = "http://tempuri.org/";
private static String URL = "http://mymachine/mywebservice/service.asmx";
private static String SOAP_ACTION = "http://tempuri.org/";
private String _soapAndMethod;
private HttpTransportSE _androidHttpTransport;
private SoapSerializationEnvelope _envelope;
private String _methodName;
public WebService(String methodName) {
_methodName = methodName;
_soapAndMethod = SOAP_ACTION + _methodName;
SoapObject request = new SoapObject(NAMESPACE, methodName);
_envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
_envelope.dotNet = true;
_envelope.setOutputSoapObject(request);
_androidHttpTransport = new HttpTransportSE(URL);
}
#Override
public void run() {
android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_BACKGROUND);
}
public String InvokeWebService() {
String resTxt = null;
try {
_androidHttpTransport.call(_soapAndMethod, _envelope);
SoapPrimitive response = (SoapPrimitive) _envelope.getResponse();
resTxt = response.toString();
} catch (Exception e){
e.printStackTrace();
}
return resTxt;
}
}
Any help would be great. Thank you to those who do respond. Is there some setting in IIS I need to change? Is there something I missed in my code?
Additional information:
When the server is responding the webservice request IIS creates a process called w3wp.exe and it this process that is running out of ports.
Doing in a little digging and experimentation the Webservice gets newed up each call to "GetDefaultResults". Which leaves w3wp.exe in a Listening state and they never go away until the iisreset is run.
Some time later it uses the remaining ports available and starts throwing that exception.
Why is it not reusing the same webservice instead of creating a new one each time.
If that is not possible what code do I write in the Webservice to close the connection after it is finished. I put in a hack to cause it close after 5 seconds to see if that would work at least.
It does clean up w3wp.exe but after a short time I start getting this exception on the client.
"expected: START_TAG {http://schemas.xmlsoap.org/soap/envelope/}Envelope (position:START_TAG #2:7 in java.io.InputStreamReader#41beb098) "
so this is not a work around but it helped me understand what the problem is a little better.
protected override void Dispose(bool disposing)
{
System.Timers.Timer timer = new System.Timers.Timer();
timer.Interval = 5000;
timer.Elapsed += timer_Elapsed;
timer.Start();
base.Dispose(disposing);
}
void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
Environment.Exit(1);
}
Thanks for your help.
If you failed your first request, you might need to enable IIS Express to allow external connections. In your case, it looks like it only failed after running for a while.
In your question, I see that you
"go to the web service gets the data and then displays it on the screen and repeats this as fast as it can go.
did not call "close" on HttpTransportSE
You might be running out of local ports. Are you reusing the connection on all your requests? If not, try to close it when you are done.
My Webservice was referencing an api to get the values from then pass them over a webservice to the android app.
The problem was that every time the webservice was being called a new reference would be created to the api and after the request was sent it would never close out the port. As soon as I stopped referencing the api everything worked.
A cludge to get this to work is I had the webservice monitor a folder and send the data in the file that was last created. Then created another program to attach to the api and output the data to that folder. Not the most elegant solution but it works as a proof of concept for what I am doing.
Still not entirely sure why the Webservice was never closing the port and I am suspect that the Webservice could not dispose of the reference to the api but I am not really sure.

VB.NET Consuming web service written for glassfish: SoapHeaderException

Wrote a 'webservice' with Netbeans wizard, runs on glassfish. I added a reference using the wsdl to my .NET client, VB if it makes any difference.
I clearly have no idea what is going on, as I am encountering some brick walls.
The issue is a SoapHeaderException.
System.Web.Services.Protocols.SoapHeaderException: com/mysql/jdbc/Connection
at System.Web.Services.Protocols.SoapHttpClientProtocol.ReadResponse(
SoapClientMessage message, WebResponse response, Stream responseStream,
Boolean asyncCall)
at System.Web.Services.Protocols.SoapHttpClientProtocol.Invoke(
String methodName, Object[] parameters)
at WSClient.WSClient.localhost.DatabaseGateService.createCustomerTable(String xml)
in C:\Project\WSClient\Web References\localhost\Reference.vb:line 40
at WSClient.USAHWSClientConsumer.TestCustomer() in
C:\Project\WSClient\Client\WSConsumer.vb:line 22
The web service itself is simple:
#WebService()
public class DatabaseGate {
private MySQLManagerImp manager;
public DatabaseGate(){
manager = new MySQLManagerImp();
}
#WebMethod(operationName = "createCustomerTable")
public void createCustomerTable(#WebParam(name = "xml") String xml) {
manager.createCustomersTable(xml);
}
}
It takes an xml string, as I did not want to pass in an abomination of arguments.
I attempt to consume the service by simply instantiating the web reference:
Dim ws As localhost.DatabaseWS = New localhost.DatabaseWS
// Create the xml string
Dim qbCustomerQueryRS As String = qbQuery.GetCustomerQueryXML()
Dim processedCustomerXML As String =
customerResponseParser.GetAllCustomerDatabaseFriendlyXML(qbCustomerQueryRS)
ws.createCustomerTable(processedCustomerXML)
I've tried writing the string in a soap envelope, but still receive the same message. So passing a string is kaputt, as it should be; why would the WS know to parse a string, and simply instantiating and calling the method from the object as if it were local isn't working the way I think it does.
What is happening?
Sounds like the WSDL references com/mysql/jdbc/Connection, which is not a class known on the .NET side. If you have control over the Web Service, add annotations to avoid serialization of external class references (like com/mysql/jdbc/Connection). If you don't, simply download the WSDL to a text file, edit it manually to remove such classes/attributes, and re-create the reference pointing to the edited file. You can change the endpoints in Web.config later.
As it turns out, the reason I was receiving
System.Web.Services.Protocols.SoapHeaderException: com/mysql/jdbc/Connection
was similar to Diego's answer (thank you for pointing me in the right direction): A reference problem.
I assumed my WS deployment worked correctly because I had tested the method that executed, but only assuming the data I needed successfully transmitted over the wire.
Testing another angle using glassfish revealed:
Service invocation threw an exception with message : null; Refer to the server log for more details
Checking the server log, the answer was obvious:
java.lang.NoClassDefFoundError: com/mysql/jdbc/Connection
I had forgotten to add the jar to com/mysql/jdbc/Connection.

Categories