That's a fair amount of code to look through, but I doubt this is a servicemix issue. Your best bet to solve why the memory isn't being deallocated is to use a profiler to be sure where the memory is being held (in your code or SMX) and then see if you can fix it, if it's your issue, or if it's a servicemix issue, report a bug on the issue with the details on where SMX is leaking memory. Once I've stabilized my services, even under heavy load I have no issues with memory management. My guess is that most likely you are holding a reference to something that you don't realize you are still holding onto.
Ryan On Tue, Feb 16, 2010 at 2:27 PM, atr <[email protected]> wrote: > > Hi. > > I have a memory allocation problem with a ServiceAssembly in Servicemix > 3.3. > A file based tranformation will be done by the following bean code. The > transformation allocates 1GB of memory. Once the transformation is > finnished > successfully with a tranformation result file, the memory won't be > de-allocated. > Waiting for several hours or days the memory will still allocated and not > released. So, the result is that the Servicemix will shut down due an out > of > memory exception. ;-( > > What is the problem with my code, is there a bug in Servicemix or what I > should change in the bean? > > Thanks a lot, > Andreas. > > Here comes my bean code: > =========================== > package de.mmsdresden.sportscheck.beans; > > import java.io.ByteArrayInputStream; > import java.io.File; > import java.io.FileNotFoundException; > import java.io.IOException; > import java.util.HashMap; > import java.util.Iterator; > import java.util.LinkedList; > import java.util.List; > import java.util.Map; > import java.util.Properties; > > import javax.annotation.PostConstruct; > import javax.annotation.Resource; > import javax.jbi.component.ComponentContext; > import javax.jbi.messaging.DeliveryChannel; > import javax.jbi.messaging.ExchangeStatus; > import javax.jbi.messaging.InOnly; > import javax.jbi.messaging.MessageExchange; > import javax.jbi.messaging.MessagingException; > import javax.jbi.messaging.NormalizedMessage; > import javax.jbi.messaging.MessageExchange.Role; > import javax.xml.transform.TransformerConfigurationException; > import javax.xml.transform.TransformerException; > import javax.xml.transform.stream.StreamResult; > import javax.xml.transform.stream.StreamSource; > > import org.apache.commons.lang.StringEscapeUtils; > import org.apache.commons.logging.Log; > import org.apache.commons.logging.LogFactory; > import org.apache.servicemix.MessageExchangeListener; > import org.apache.servicemix.client.ServiceMixClientFacade; > import org.apache.servicemix.components.util.DefaultFileMarshaler; > import org.apache.servicemix.jbi.api.Destination; > import org.apache.servicemix.jbi.api.ServiceMixClient; > import org.jdom.Document; > import org.jdom.Element; > import org.jdom.JDOMException; > import org.jdom.input.SAXBuilder; > import org.jdom.output.XMLOutputter; > import org.milyn.payload.JavaResult; > import org.xml.sax.SAXException; > > import > de.mmsdresden.sportscheck.pojos.pricesbfs.demandware.input.BfsPriceInfo; > import de.mmsdresden.sportscheck.pojos.pricesbfs.demandware.input.Item; > import > de.mmsdresden.sportscheck.pojos.pricesbfs.demandware.input.PriceBook; > import de.mmsdresden.sportscheck.utils.FileNameUtils; > import de.mmsdresden.sportscheck.utils.LoggingUtils; > import de.mmsdresden.sportscheck.utils.Mail; > import de.mmsdresden.sportscheck.utils.MessageExchangeCache; > import de.mmsdresden.sportscheck.utils.MessageExchangeCacheImpl; > import de.mmsdresden.sportscheck.utils.ServiceMixUtils; > import de.mmsdresden.sportscheck.utils.SmooksWrapper; > import de.mmsdresden.sportscheck.utils.XMLUtils; > import de.mmsdresden.sportscheck.utils.properties.PropertyLoader; > import > > de.mmsdresden.sportscheck.utils.properties.factories.FilenamePropertyFactory; > import > de.mmsdresden.sportscheck.utils.properties.factories.MailPropertyFactory; > > /** > * DW -> BFS Price Mapping > * > * @author Andreas Lutz > * @since 03.08.2009 > */ > > public class PriceBean implements MessageExchangeListener { > /** > * @see javax.jbi.messaging.DeliveryChannel > */ > @Resource > private DeliveryChannel channel; > > /** > * @see javax.jbi.component.ComponentContext > */ > @Resource > private ComponentContext context; > > private ServiceMixClient client; > > private Destination fileoutProduction; > > private Destination fileoutTest; > > private static Log LOGGER = LogFactory.getLog(PriceBean.class); > > private static final String SERVICE_NAMESPACE = > "service:http://sportscheck.com/services/pricesbfs/"; > > private static final String FILEOUT_PRODUCTION_ENDPOINT = > SERVICE_NAMESPACE > + "PricesOutProduction"; > > private static final String FILEOUT_TEST_ENDPOINT = > SERVICE_NAMESPACE + > "PricesOutTest"; > > private static final String SMOOKS_PRICE_INPUT_CONF = > "smooks_conf/pricesbfs_dmware_input.xml"; > > private static final String SMOOKS_PRICE_OUTPUT_CONF = > "smooks_conf/pricesbfs_bfs_output.xml"; > > private MessageExchangeCache exchangeCache = new > MessageExchangeCacheImpl(); > > private PropertyLoader propsFilename = null; > > private String fileOutName; > > private String fileInName; > > private static final String PROPERTIES_PATH_TEST = > "baur.import.test.prices"; > > private static final String PROPERTIES_PATH_PRODUCTION = > "baur.import.production.prices"; > > private static final String DEFAULT_XSL_PATH = > "sportscheck_conf/XSL/"; > > private static final String DW_XSL = "DW/dw_prices.xsl"; > > private static String GLOBAL_ERROR; > > private static String GLOBAL_PROCESS_INVALID_FILES; > > static javax.xml.transform.TransformerFactory factory = > javax.xml.transform.TransformerFactory.newInstance(); > > // some Mail constants // > private static String MAIL_SENDMAIL; > > private static String MAIL_SENDER; > > private static String MAIL_RECEIVERS; > > private static String[] MAIL_RECEIVERS_ARRAY; > > private static Mail MAIL; > > private static PropertyLoader props = null; > > static { > try { > props = new > MailPropertyFactory().getImplementation(); > } catch (FileNotFoundException e) { > LOGGER.error(e); > } catch (IOException e) { > LOGGER.error(e); > } > GLOBAL_PROCESS_INVALID_FILES = > props.getValue("global.processInvalidFiles"); > MAIL = new Mail(); > MAIL.setSmtpHost(props.getValue("smtp_host"), > props.getValue("smtp_user"), > props.getValue("smtp_pass")); > MAIL_SENDMAIL = > props.getValue("esb.pricesbfs.validateGeneratedXML.invalid.sendmail"); > } > > /** > * This init method checks that the needed artifacts are initialized > * > * @throws IOException > * @throws FileNotFoundException > * @throws MessagingException > */ > @PostConstruct > public void init() throws FileNotFoundException, IOException, > MessagingException { > if (this.context == null || this.channel == null) { > throw new IllegalStateException("Bean not > initialized"); > } > this.propsFilename = new > FilenamePropertyFactory().getImplementation(); > this.fileOutName = > this.propsFilename.getValue("pricebooks"); > > /* > * Create client to get the destination (where to send the > files) > */ > this.client = new ServiceMixClientFacade(this.context); > > this.fileoutProduction = > this.client.createDestination(FILEOUT_PRODUCTION_ENDPOINT); > this.fileoutTest = > this.client.createDestination(FILEOUT_TEST_ENDPOINT); > > > LOGGER.info("-----------------------------------------------"); > LOGGER.info("-------- PriceBFS mapping initialized > ---------"); > > LOGGER.info("-----------------------------------------------"); > LOGGER.info("-> For more informations turn on debug > logging."); > } > > /* > * (non-Javadoc) > * > * @see > * > org.apache.servicemix.MessageExchangeListener#onMessageExchange(javax > * .jbi.messaging.MessageExchange) > */ > public synchronized void onMessageExchange(MessageExchange exchange) > throws > MessagingException { > LOGGER.debug("Received Exchange: " + > exchange.getExchangeId()); > > if (exchange.getRole().equals(Role.CONSUMER)) { > if > (this.exchangeCache.containsKey(exchange.getExchangeId())) { > boolean done = true; > boolean error = false; > LOGGER.debug("Exchange has status: " + > exchange.getStatus()); > if > (exchange.getStatus().equals(ExchangeStatus.ACTIVE)) > done = false; > if > (exchange.getStatus().equals(ExchangeStatus.ERROR)) > error = true; > if (done && !error) { > LOGGER.debug("Setting exchange: " + > exchange.getExchangeId() + " to > DONE!"); > > ServiceMixUtils.sendMessage(exchange, ExchangeStatus.DONE, > this.channel); > > this.exchangeCache.removeFromCache(exchange.getExchangeId()); > } > } > } else { > try { > process(exchange); > ServiceMixUtils.sendMessage(exchange, > ExchangeStatus.DONE, > this.channel); > } catch (IOException e) { > LOGGER.error(e); > } catch (SAXException e) { > LOGGER.error(e); > } catch (TransformerException e) { > LOGGER.error(e); > } > } > LOGGER.debug("Exchanges in cache: " + > this.exchangeCache.size()); > } > > private void process(MessageExchange exchange) throws > TransformerException, > IOException, SAXException, MessagingException { > InOnly inExchange = (InOnly) exchange; > NormalizedMessage message = inExchange.getInMessage(); > String filePath = (String) > message.getProperty(DefaultFileMarshaler.FILE_PATH_PROPERTY); > fileInName = (String) > message.getProperty(DefaultFileMarshaler.FILE_NAME_PROPERTY); > StreamSource content = > ServiceMixUtils.getMessagePayload(message); > LOGGER.info("Processing Exchange Message, with incoming file > name " + > fileInName); > > // fix DW XML (Smooks only works with unique tag-ids) // > LOGGER.info("Fixing DW XML file ..."); > content = fixedXML(content); > > // get XML into JAVA // > LOGGER.info("Mapping XML to Java ..."); > List<PriceBook> in_prices = xmlTojava(content); > > // unescape String // > LOGGER.info("Mapping escaped String to Java ..."); > mapEscapedXMLString(in_prices); > > // create XML from JAVA // > LOGGER.info("Creating XML from Java ..."); > StreamResult out = javaToxml(in_prices); > > // validate generated xml // > LOGGER.info("Validating generated XML ..."); > boolean isvalid = validate(filePath, out); > if (!isvalid && MAIL_SENDMAIL.equals("1")) { > sendErrorMail(filePath); > } > > // ouput XML // > if (isvalid || (!isvalid && > GLOBAL_PROCESS_INVALID_FILES.equals("1"))) { > LOGGER.info("Saving XML to Filesystem ..."); > outputToFile(filePath, out); > } > > // Done // > LOGGER.info("Done processing exchange message ..."); > } > > private StreamSource fixedXML(StreamSource content) throws > IOException, > TransformerConfigurationException, FileNotFoundException { > SAXBuilder sb = new SAXBuilder(); > try { > Document doc = sb.build(content.getInputStream()); > Element root = doc.getRootElement(); > Element transformed = XMLUtils.modifyXML(root, > System.getProperty("user.dir") + File.separator + DEFAULT_XSL_PATH + > DW_XSL); > > XMLOutputter xo = new XMLOutputter(); > // xo.output(transformed, new > FileWriter("c:\\test.xml")); > return new StreamSource(new > ByteArrayInputStream(xo.outputString(transformed).getBytes())); > > } catch (JDOMException e) { > LOGGER.error("Error parsing XML JDOM - " + e); > return null; > } > } > > private StreamResult javaToxml(List<PriceBook> prices) throws > IOException, > SAXException { > SmooksWrapper xmlMapper = SmooksWrapper.getInstance(); > Map<String, Object> outObjects = new HashMap<String, > Object>(); > outObjects.put("transformedPrices", prices); > StreamResult out = > xmlMapper.mapJavaToXML(SMOOKS_PRICE_OUTPUT_CONF, > outObjects); > return out; > } > > private void mapEscapedXMLString(List<PriceBook> in_prices) throws > IOException, SAXException { > Iterator<PriceBook> book_iter = in_prices.iterator(); > while (book_iter.hasNext()) { > PriceBook book = book_iter.next(); > if (!book.getBfsPriceInfoString().equals("")) { > String unescaped = > StringEscapeUtils.unescapeXml(book.getBfsPriceInfoString()); > unescaped = unescaped.replace("&null;", ""); > SmooksWrapper xmlMapper = > SmooksWrapper.getInstance(); > JavaResult result = > xmlMapper.mapXMLtoJava(SMOOKS_PRICE_INPUT_CONF, new > StreamSource(new ByteArrayInputStream(unescaped > .getBytes()))); > book.setBfsPriceInfo((BfsPriceInfo) > result.getBean("bfsPriceInfo")); > // create map out of arraylist // > Iterator<Item> iter = > book.getBfsPriceInfo().getItemsList().iterator(); > HashMap<String, Item> map = new > HashMap<String, Item>(); > while (iter.hasNext()) { > Item item = iter.next(); > map.put(item.getProductId(), item); > } > book.getBfsPriceInfo().setItemsMap(map); > } > } > } > > @SuppressWarnings("unchecked") > private List<PriceBook> xmlTojava(StreamSource content) throws > IOException, > SAXException { > SmooksWrapper xmlMapper = SmooksWrapper.getInstance(); > JavaResult result = > xmlMapper.mapXMLtoJava(SMOOKS_PRICE_INPUT_CONF, > content); > List<PriceBook> in_prices = (LinkedList<PriceBook>) > result.getBean("pricebooks"); > return in_prices; > } > > private boolean validate(String filePath, StreamResult out) { > String path = null; > if (ServiceMixUtils.isTestDir(filePath)) > path = PROPERTIES_PATH_TEST; > else > path = PROPERTIES_PATH_PRODUCTION; > try { > XMLUtils.validateXML(out.getOutputStream(), path); > } catch (Exception e) { > LOGGER.error("Exception: " + e); > GLOBAL_ERROR = e.getMessage(); > return false; > } > return true; > } > > private void sendErrorMail(String filePath) { > MAIL_SENDER = > props.getValue("esb.pricesbfs.validateGeneratedXML.invalid.sender"); > MAIL_RECEIVERS = > props.getValue("esb.pricesbfs.validateGeneratedXML.invalid.receivers"); > // split receivers // > if (MAIL_RECEIVERS.indexOf("|") > -1) { > MAIL_RECEIVERS_ARRAY = MAIL_RECEIVERS.split("\\|"); > } else { > MAIL_RECEIVERS_ARRAY = new String[1]; > MAIL_RECEIVERS_ARRAY[0] = new > String(MAIL_RECEIVERS); > } > MAIL.setContent(MAIL_SENDER, "Error while validating > generated Baur price > file"); > MAIL.addRecipients(MAIL_RECEIVERS_ARRAY); > MAIL.addText("Error validating " + filePath + ":"); > MAIL.addText(GLOBAL_ERROR); > if (!MAIL.sendMail()) { > LOGGER.error("Could not sent mail.\r\n Error: " + > MAIL.lastError); > } > } > > private void outputToFile(String filePath, StreamResult out) throws > MessagingException, IOException { > MessageExchange[] exchanges = null; > String fileOutTotal = > FileNameUtils.getOutFilenameWithUniqueKey(this.fileOutName, fileInName, > ".xml"); > > if (ServiceMixUtils.isTestDir(filePath)) { > exchanges = new MessageExchange[1]; > // fileout test copy // > Properties fileOutProps = new Properties(); > > fileOutProps.put(DefaultFileMarshaler.FILE_NAME_PROPERTY, fileOutTotal); > exchanges[0] = > ServiceMixUtils.sendMessage(this.fileoutTest, out, > fileOutProps, this.client); > LOGGER.debug("Exchange created - Production file: " > + > exchanges[0].getExchangeId() + ", with outgoing file name " > + fileOutTotal + > LoggingUtils.printSize(out)); > > } else { > exchanges = new MessageExchange[1]; > // fileout production copy // > Properties fileOutProps = new Properties(); > > fileOutProps.put(DefaultFileMarshaler.FILE_NAME_PROPERTY, fileOutTotal); > exchanges[0] = > ServiceMixUtils.sendMessage(this.fileoutProduction, out, > fileOutProps, this.client); > LOGGER.debug("Exchange created - file: " + > exchanges[0].getExchangeId() + > ", with outgoing file name " + fileOutTotal > + LoggingUtils.printSize(out)); > } > } > } > > -- > View this message in context: > http://old.nabble.com/Memory-leak-or-no-de-allocation-of-memory-tp27613701p27613701.html > Sent from the ServiceMix - User mailing list archive at Nabble.com. > >
