1 2 Previous Next 15 Replies Latest reply: Feb 10, 2011 12:05 PM by 796440 RSS

    Static methods in concurrency

    811242
      I have a static method which takes a few String and double parameters and contains only local variables. When it is called by multiple threads there seems to be an exception thrown intermittenly. I got a little paranoid and so I've changed it to an instance method, and now the problem seems to disappear.

      Is this just a coincidence? Is my static method intrinsically thread-safe? Or are there any concurrency issues with static methods that I'm not aware of?

      Any reply is much appreciated!
        • 1. Re: Static methods in concurrency
          java4ever
          Kinldy post the code... AND the exact Exception
          For any comments to be made ;)

          Edited by: RainaV on Feb 10, 2011 4:16 PM
          • 2. Re: Static methods in concurrency
            Kayaman
            808239 wrote:
            I have a static method which takes a few String and double parameters and contains only local variables. When it is called by multiple threads there seems to be an exception thrown intermittenly. I got a little paranoid and so I've changed it to an instance method, and now the problem seems to disappear.
            Which exception?
            Is this just a coincidence? Is my static method intrinsically thread-safe? Or are there any concurrency issues with static methods that I'm not aware of?
            If there's no shared data (or rather, resources) then there's no worries. Hard to say anything else with such a vague description.
            • 3. Re: Static methods in concurrency
              811242
              public static net.opengis.sos.v_1_0_0.InsertObservationResponse insertObservation(String serverURL, String AssignedSensorId, String dataType, String timeFrom, String timeTo, String srsName, double x, double y, long numElement, String dataString) throws MalformedURLException, IOException, JAXBException, ParserConfigurationException {
                      OutputStream out = null;
                      InputStream in = null;
              
                      try {
                          URL url = new URL(serverURL);
                          HttpURLConnection connection = (HttpURLConnection) url.openConnection();
                          connection.setDoOutput(true);
                          connection.setRequestMethod("POST");
                          connection.setRequestProperty("Content-type", "text/xml, application/xml");
                          out = connection.getOutputStream();
              
                          JAXBContext jaxbContext = JAXBContext.newInstance("net.opengis.sos.v_1_0_0:net.opengis.ows.v_1_1_0:net.opengis.sos.v_1_0_0.filter.v_1_1_0:net.opengis.sensorml.v_1_0_1:net.opengis.swe.v_1_0_1:net.opengis.om.v_1_0_0:net.opengis.gml.v_3_1_1:net.opengis.sampling.v_1_0_0");
              
                          /////////////////////////////////request
                          Marshaller marshaller = jaxbContext.createMarshaller();
                          marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
              
              
                          //////////////////////////////////////object factories
                          net.opengis.gml.v_3_1_1.ObjectFactory gmlOF = new net.opengis.gml.v_3_1_1.ObjectFactory();
                          net.opengis.swe.v_1_0_1.ObjectFactory sweOF = new net.opengis.swe.v_1_0_1.ObjectFactory();
                          net.opengis.sampling.v_1_0_0.ObjectFactory saOF = new net.opengis.sampling.v_1_0_0.ObjectFactory();
              
                          ////////////////////////////////////////////////////////////////////////////////////////////////getObservation request
                          net.opengis.sos.v_1_0_0.InsertObservation insertObservation = new net.opengis.sos.v_1_0_0.InsertObservation();
                          insertObservation.setAssignedSensorId(AssignedSensorId);
              
                          net.opengis.om.v_1_0_0.ObservationType observation = new net.opengis.om.v_1_0_0.ObservationType();
              
              
                          ///////////////////////////////om:samplingTime
                          //begin position
                          net.opengis.gml.v_3_1_1.TimePositionType beginTimePosition = new net.opengis.gml.v_3_1_1.TimePositionType();
                          beginTimePosition.getValue().add(timeFrom);
                          //end position
                          net.opengis.gml.v_3_1_1.TimePositionType endTimePosition = new net.opengis.gml.v_3_1_1.TimePositionType();
                          endTimePosition.getValue().add(timeTo);
                          //time period
                          net.opengis.gml.v_3_1_1.TimePeriodType timePeriod = new net.opengis.gml.v_3_1_1.TimePeriodType();
                          timePeriod.setBeginPosition(beginTimePosition);
                          timePeriod.setEndPosition(endTimePosition);
              
                          net.opengis.swe.v_1_0_1.TimeObjectPropertyType timeObjectPropertyType = new net.opengis.swe.v_1_0_1.TimeObjectPropertyType();
                          timeObjectPropertyType.setTimeObject(gmlOF.createTimePeriod(timePeriod));
              //            timeObjectPropertyType.setTimeObject(new JAXBElement(new QName("http://www.opengis.net/gml", "name"), net.opengis.gml.v_3_1_1.TimePeriodType.class, timePeriod));
                          observation.setSamplingTime(timeObjectPropertyType);
              
              
                          /////////////////////////////////om:procedure
                          net.opengis.om.v_1_0_0.ProcessPropertyType processPropertyType = new net.opengis.om.v_1_0_0.ProcessPropertyType();
                          processPropertyType.setHref(AssignedSensorId);
                          observation.setProcedure(processPropertyType);
              
              
                          /////////////////////////////////om:observedProperty
                          net.opengis.swe.v_1_0_1.CompositePhenomenonType compositePhenomenonType = new net.opengis.swe.v_1_0_1.CompositePhenomenonType();
                          compositePhenomenonType.setId("cpid0");
                          compositePhenomenonType.setDimension(BigInteger.ONE);
              
                          net.opengis.gml.v_3_1_1.CodeType codeType = new net.opengis.gml.v_3_1_1.CodeType();
                          codeType.setValue("resultComponents");
                          compositePhenomenonType.getName().add(new JAXBElement(new QName("http://www.opengis.net/gml", "name"), net.opengis.gml.v_3_1_1.CodeType.class, codeType));
              
                          net.opengis.swe.v_1_0_1.PhenomenonPropertyType phenomenonPropertyType1 = new net.opengis.swe.v_1_0_1.PhenomenonPropertyType();
                          phenomenonPropertyType1.setHref("urn:ogc:data:time:iso8601");
                          compositePhenomenonType.getComponent().add(phenomenonPropertyType1);
                          net.opengis.swe.v_1_0_1.PhenomenonPropertyType phenomenonPropertyType2 = new net.opengis.swe.v_1_0_1.PhenomenonPropertyType();
                          phenomenonPropertyType2.setHref("Abfluss");
                          compositePhenomenonType.getComponent().add(phenomenonPropertyType2);
              
                          net.opengis.swe.v_1_0_1.PhenomenonPropertyType observedProperty = new net.opengis.swe.v_1_0_1.PhenomenonPropertyType();
                          observedProperty.setPhenomenon(sweOF.createCompositePhenomenon(compositePhenomenonType));
                          observation.setObservedProperty(observedProperty);
              
              
                          ////////////////////////////////om:featureOfInterest
                          net.opengis.sampling.v_1_0_0.SamplingPointType samplingPoint = new net.opengis.sampling.v_1_0_0.SamplingPointType();
                          samplingPoint.setId(AssignedSensorId);
                          net.opengis.gml.v_3_1_1.CodeType saName = new net.opengis.gml.v_3_1_1.CodeType();
                          saName.setValue(AssignedSensorId);
                          samplingPoint.getName().add(new JAXBElement(new QName("http://www.opengis.net/gml", "name"), net.opengis.gml.v_3_1_1.CodeType.class, saName));
              
                          //samplingPoint.getSampledFeature().add(gmlOF.createFeaturePropertyType());
              
                          net.opengis.gml.v_3_1_1.DirectPositionType pos = new net.opengis.gml.v_3_1_1.DirectPositionType();
                          pos.setSrsName(srsName/*"urn:ogc:def:crs:EPSG:4326"*/);
                          pos.getValue().add(x);
                          pos.getValue().add(y);
                          net.opengis.gml.v_3_1_1.PointType point = new net.opengis.gml.v_3_1_1.PointType();
                          point.setPos(pos);
                          net.opengis.gml.v_3_1_1.PointPropertyType pointProperty = new net.opengis.gml.v_3_1_1.PointPropertyType();
                          pointProperty.setPoint(point);
                          samplingPoint.setPosition(pointProperty);
                          net.opengis.gml.v_3_1_1.FeaturePropertyType featureMember = new net.opengis.gml.v_3_1_1.FeaturePropertyType();
                          featureMember.setFeature(saOF.createSamplingPoint(samplingPoint));
              
              
                          net.opengis.gml.v_3_1_1.FeatureCollectionType featureCollectionType = new net.opengis.gml.v_3_1_1.FeatureCollectionType();
                          featureCollectionType.getFeatureMember().add(featureMember);
              
                          net.opengis.gml.v_3_1_1.FeaturePropertyType featureOfInterest = new net.opengis.gml.v_3_1_1.FeaturePropertyType();
                          featureOfInterest.setFeature(gmlOF.createFeatureCollection(featureCollectionType));
              //            featureOfInterest.setFeature(new JAXBElement(new QName("http://www.opengis.net/gml", "name"), net.opengis.gml.v_3_1_1.FeatureCollectionType.class, featureCollectionType));
              
                          observation.setFeatureOfInterest(featureOfInterest);
              
              
                          
              
              
                          DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
                          factory.setNamespaceAware(true);
                          DocumentBuilder builder = factory.newDocumentBuilder();
                          Document doc = builder.newDocument();
              
                          final String sweNS = "http://www.opengis.net/swe/1.0.1";
                          Element dataArray = doc.createElementNS(sweNS, "swe:DataArray");
                          Element elementCount = doc.createElementNS(sweNS, "swe:elementCount");
                          Element count = doc.createElementNS(sweNS, "swe:Count");
                          Element value = doc.createElementNS(sweNS, "swe:value");
                          dataArray.appendChild(elementCount).appendChild(count).appendChild(value).appendChild(doc.createTextNode(String.valueOf(numElement)));
              
                          Element elementType = doc.createElementNS(sweNS, "swe:elementType");
                          elementType.setAttribute("name", "Components");
                          Element simpleDataRecord = doc.createElementNS(sweNS, "swe:SimpleDataRecord");
                          Element timeField = doc.createElementNS(sweNS, "swe:field");
                          timeField.setAttribute("name", "Time");
                          Element time = doc.createElementNS(sweNS, "swe:Time");
                          time.setAttribute("definition", "urn:ogc:data:time:iso8601");
                          Element featureField = doc.createElementNS(sweNS, "swe:field");
                          featureField.setAttribute("name", "feature");
                          Element text = doc.createElementNS(sweNS, "swe:Text");
                          text.setAttribute("definition", "urn:ogc:data:feature");
                          Element dataField = doc.createElementNS(sweNS, "swe:field");
                          dataField.setAttribute("name", dataType);
                          Element quantity = doc.createElementNS(sweNS, "swe:Quantity");
                          quantity.setAttribute("definition", dataType);
                          Element uom = doc.createElementNS(sweNS, "swe:uom");
                          uom.setAttribute("code", "m3 per s");
              
                          simpleDataRecord.appendChild(timeField).appendChild(time);
                          simpleDataRecord.appendChild(featureField).appendChild(text);
                          simpleDataRecord.appendChild(dataField).appendChild(quantity).appendChild(uom);
                          dataArray.appendChild(elementType).appendChild(simpleDataRecord);
              
                          Element encoding = doc.createElementNS(sweNS, "swe:encoding");
                          Element textBlock = doc.createElementNS(sweNS, "swe:TextBlock");
                          textBlock.setAttribute("decimalSeparator", ".");
                          textBlock.setAttribute("tokenSeparator", ",");
                          textBlock.setAttribute("blockSeparator", ";");
                          dataArray.appendChild(encoding).appendChild(textBlock);
              
                          Element sweValues = doc.createElementNS(sweNS, "swe:values");
                          dataArray.appendChild(sweValues).appendChild((doc.createTextNode(dataString)));
              
                          Element result = doc.createElementNS("http://www.opengis.net/om/1.0", "om:result");
                          result.appendChild(dataArray);
                          observation.setResult(result);
              
              
                          insertObservation.setObservation(observation);
              
                          //handle "ogc" namespace bug
                          NamespacePrefixMapper mapper = new PreferredMapper();
                          marshaller.setProperty("com.sun.xml.bind.namespacePrefixMapper", mapper);
              
              
                          marshaller.marshal(insertObservation, System.out);
                          marshaller.marshal(insertObservation, out);
              
                          Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
                          in = connection.getInputStream();
              
              
                          Object response = unmarshaller.unmarshal(new StreamSource(in));
              
                          if (response instanceof net.opengis.sos.v_1_0_0.InsertObservationResponse) {
                              return (net.opengis.sos.v_1_0_0.InsertObservationResponse) response;
                          } else if (response instanceof net.opengis.ows.v_1_1_0.ExceptionReport) {
                              net.opengis.ows.v_1_1_0.ExceptionReport exceptionReport = (net.opengis.ows.v_1_1_0.ExceptionReport) response;
              
                              StringBuilder strBuilder = new StringBuilder();
                              for (net.opengis.ows.v_1_1_0.ExceptionType ex : exceptionReport.getException()) {
                                  StringBuilder tempBuilder = new StringBuilder(ex.getExceptionCode() + ": ");
                                  for (String temp : exceptionReport.getException().get(0).getExceptionText()) {
                                      tempBuilder.append(temp + "\n");
                                  }
                                  strBuilder.append(tempBuilder.toString() + "\n");
                              }
                              throw new IllegalArgumentException(strBuilder.toString());
                          } else {
                              throw new IllegalStateException("Unrecognizeable response type!");
                          }
              
                      } finally {
                          if (out != null) {
                              out.close();
                          }
                          if (in != null) {
                              in.close();
                          }
                      }
                  }
              Edited by: 808239 on 10-Feb-2011 02:44
              • 4. Re: Static methods in concurrency
                811242
                The exception is thrown AT
                Object response = unmarshaller.unmarshal(new StreamSource(in));
                javax.xml.bind.UnmarshalException
                - with linked exception:
                [org.xml.sax.SAXParseException: Premature end of file.]
                at javax.xml.bind.helpers.AbstractUnmarshallerImpl.createUnmarshalException(AbstractUnmarshallerImpl.java:315)
                at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallerImpl.createUnmarshalException(UnmarshallerImpl.java:514)
                at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal0(UnmarshallerImpl.java:215)
                at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal(UnmarshallerImpl.java:184)
                at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:137)
                at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:105)
                • 5. Re: Static methods in concurrency
                  java4ever
                  What you posted has not much to do with concurrency i presume...

                  see google for the same exception as it a JAXB issue

                  You can see a old thread Premature End Of File - SaxParseException


                  808239 wrote:
                  The exception is thrown AT
                  Object response = unmarshaller.unmarshal(new StreamSource(in));
                  javax.xml.bind.UnmarshalException
                  - with linked exception:
                  [org.xml.sax.SAXParseException: Premature end of file.]
                  at javax.xml.bind.helpers.AbstractUnmarshallerImpl.createUnmarshalException(AbstractUnmarshallerImpl.java:315)
                  at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallerImpl.createUnmarshalException(UnmarshallerImpl.java:514)
                  at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal0(UnmarshallerImpl.java:215)
                  at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal(UnmarshallerImpl.java:184)
                  at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:137)
                  at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:105)
                  • 6. Re: Static methods in concurrency
                    811242
                    It's pretty weird that I let the program run several times day by day when there was 1 thread using this method and it was cool. Now I've just increased to a few threads and I get this exception rather frequently.

                    Maybe just a nasty coincidence _+

                    So in theory there should be no concurrency problem with such a static method like this one, I assume.

                    Thanks for all your replies!
                    • 7. Re: Static methods in concurrency
                      YoungWinston
                      808239 wrote:
                      So in theory there should be no concurrency problem with such a static method like this one, I assume.
                      If you're really worried about it, you could add a lock object. Maybe something like:
                      private static final Object observationLock = new Object();
                      public static net...InsertObservationResponse insertObservation(...) {
                         synchronized(observationLock) {
                            // rest of your code
                         }
                      }
                      which would save locking the class containing the method (not usually a good idea).

                      However, I'd read the thread that RainaV posted first and see if anything comes to mind, because the above is far from ideal.

                      Also, that does seem like an incredibly convoluted method, so it doesn't surprise me that the bug is hard to find.
                      Is there no way you could break it down? Or at least encapsulate the parameters in some class (Observation?).

                      Winston
                      • 8. Re: Static methods in concurrency
                        Kayaman
                        808239 wrote:
                        Maybe just a nasty coincidence
                        There are no coincidences in programming.
                        So in theory there should be no concurrency problem with such a static method like this one, I assume.
                        Well a static method by itself shouldn't affect concurrency, what matters is how it's implemented and what it does.

                        But your method there...I assume it's generated code?

                        The exception does sound a bit like there's two threads sharing the same resource though.
                        • 9. Re: Static methods in concurrency
                          811242
                          @Winston: Thanks for the suggestion. If I might try that out and see if the problem comes back, then I can be sure it's a concurrency problem ;)

                          @Kayaman: The code is not generated by some tool; it was hand-written.
                          • 10. Re: Static methods in concurrency
                            Kayaman
                            808239 wrote:
                            @Kayaman: The code is not generated by some tool; it was hand-written.
                            Was it hand-written by a tool?

                            Having a huge method that accepts 10 or so parameters...that's ridiculous. Now nobody can even debug it properly, because it's a huge, steaming pile of...code that makes no sense to a human reader.

                            I'd refactor the method heavily, then it would be possible to identify if there are any concurrency issues. Now pretty much all you can do is hope and guess.
                            • 11. Re: Static methods in concurrency
                              jwenting
                              Kayaman wrote:
                              808239 wrote:
                              @Kayaman: The code is not generated by some tool; it was hand-written.
                              Was it hand-written by a tool?
                              handwritten by a fool you mean?
                              Having a huge method that accepts 10 or so parameters...that's ridiculous. Now nobody can even debug it properly, because it's a huge, steaming pile of...code that makes no sense to a human reader.
                              I've seen worse, sadly, that was handwritten.
                              Usually it was handwritten to match the signature of a template generated by some generator, or in order to comply with the brainfarts of some high and mighty "architect" who never wrote a line of code in his lilfe, whose entire career exists of making UML diagrams and "design documents".
                              • 12. Re: Static methods in concurrency
                                YoungWinston
                                808239 wrote:
                                @Winston: Thanks for the suggestion. If I might try that out and see if the problem comes back, then I can be sure it's a concurrency problem ;)
                                Actually, if it's a concurrency issue, the lock will hopefully make it go away.
                                I should also point out that such a "funneling" technique may cause your multi-threaded code to run slower than it did when it was single-threaded.

                                I also wouldn't recommend it as a permanent solution. You need to find out where/what the bug is - definitively.

                                Winston
                                • 13. Re: Static methods in concurrency
                                  811242
                                  Most of the classes used in the method are generated by the JAXB xjc tool, and that "huge" method you see there generates an XML document that is pretty humble in size.

                                  After you work with JAXB for a while your eyes just kind of get used to it ;)
                                  • 14. Re: Static methods in concurrency
                                    Kayaman
                                    808239 wrote:
                                    Most of the classes used in the method are generated by the JAXB xjc tool, and that "huge" method you see there generates an XML document that is pretty humble in size.
                                    To a programmer it doesn't really matter what the result is. Otherwise you could say that all wrongly implemented algorithms that return a simple int are just a-ok.
                                    After you work with JAXB for a while your eyes just kind of get used to it ;)
                                    Granted, XML binding will do that to you. But I still think the method is doing too much at once. You can't blame everything on JAXB.
                                    When you divide big methods into smaller methods, debugging becomes a lot easier.
                                    1 2 Previous Next