\n ...\n\u003C/Persons>\n",[45,5778,5779,5784,5789,5794,5799],{"__ignoreMap":43},[48,5780,5781],{"class":50,"line":51},[48,5782,5783],{},"\u003C?xml version=\"1.0\" encoding=\"UTF-8\"?>\n",[48,5785,5786],{"class":50,"line":57},[48,5787,5788],{},"\u003CPersons>\n",[48,5790,5791],{"class":50,"line":63},[48,5792,5793],{}," \u003CPerson firstname=\"First\" lastname=\"Last\" mail=\"first.last@test.test\" title=\"nice guy\" age=\"47\" status=\"married\"/>\n",[48,5795,5796],{"class":50,"line":69},[48,5797,5798],{}," ...\n",[48,5800,5801],{"class":50,"line":75},[48,5802,5803],{},"\u003C/Persons>\n",[635,5805,5807],{"id":5806},"the-custom-data-source","The custom data source",[18,5809,5810,5811,5814],{},"The custom data source extends the ",[974,5812,5813],{},"JRAbstractTextDataSource"," and therefore the sample implementation has to override\nthe methods",[868,5816,5817,5823],{},[871,5818,5819,5822],{},[275,5820,5821],{},"boolean next():"," Determines whether or not there is another row to display",[871,5824,5825,5828],{},[275,5826,5827],{},"Object getFieldValue(JRField field)",": Requests the value for the given field/cell",[18,5830,5831],{},"It simply implements the Iterator pattern in order to render all columns of the report.",[18,5833,5834],{},[974,5835,5836],{},"Initialization",[18,5838,5839,5840,5843],{},"The constructor of the class expects an Inputstream that represents the XML source. Based on that stream the class\ninitializes a ",[974,5841,5842],{},"XMLStreamReader"," which is basically an iterator over the XML tags.",[18,5845,5846],{},[974,5847,5848],{},"boolean next()",[18,5850,5851,5852,5855],{},"The implementation of the ",[275,5853,5854],{},"next()"," method initially iterates over the XML tags till it reaches the first Person tag and\nstops at this point. Unfortunately this means that the custom implementation contains knowledge about how the XML is\nstructured and makes it very hard to reuse.",[18,5857,5858,5859,5861],{},"Every subsequent call to the ",[275,5860,5854],{}," method sets the current pointer to the next Person element and returns true, until\nthe Persons tag has been reached or the end of the document appeared.",[38,5863,5865],{"className":40,"code":5864,"language":42,"meta":43,"style":43}," int eventType = xmlStreamReader.getEventType();\n String tagName = null;\n boolean isStart = false;\n while (xmlStreamReader.hasNext()) {\n eventType = xmlStreamReader.next();\n switch (eventType) {\n case XMLEvent.START_ELEMENT:\n isStart = true;\n case XMLEvent.END_ELEMENT:\n tagName = xmlStreamReader.getLocalName();\n // check if there is still a person element left\n if (isStart && PERSON_TAG_NAME.equals(tagName)) {\n return true;\n } else if (!isStart && PERSONS_TAG_NAME.equals(tagName)) {\n // end tag of persons, nothing else to handle\n return false;\n }\n break;\n case XMLEvent.END_DOCUMENT:\n return false;\n }\n isStart = false;\n }\n",[45,5866,5867,5872,5877,5882,5887,5892,5897,5902,5907,5912,5917,5922,5927,5932,5937,5942,5947,5952,5957,5962,5967,5972,5977],{"__ignoreMap":43},[48,5868,5869],{"class":50,"line":51},[48,5870,5871],{}," int eventType = xmlStreamReader.getEventType();\n",[48,5873,5874],{"class":50,"line":57},[48,5875,5876],{}," String tagName = null;\n",[48,5878,5879],{"class":50,"line":63},[48,5880,5881],{}," boolean isStart = false;\n",[48,5883,5884],{"class":50,"line":69},[48,5885,5886],{}," while (xmlStreamReader.hasNext()) {\n",[48,5888,5889],{"class":50,"line":75},[48,5890,5891],{}," eventType = xmlStreamReader.next();\n",[48,5893,5894],{"class":50,"line":81},[48,5895,5896],{}," switch (eventType) {\n",[48,5898,5899],{"class":50,"line":124},[48,5900,5901],{}," case XMLEvent.START_ELEMENT:\n",[48,5903,5904],{"class":50,"line":129},[48,5905,5906],{}," isStart = true;\n",[48,5908,5909],{"class":50,"line":204},[48,5910,5911],{}," case XMLEvent.END_ELEMENT:\n",[48,5913,5914],{"class":50,"line":210},[48,5915,5916],{}," tagName = xmlStreamReader.getLocalName();\n",[48,5918,5919],{"class":50,"line":216},[48,5920,5921],{}," // check if there is still a person element left\n",[48,5923,5924],{"class":50,"line":357},[48,5925,5926],{}," if (isStart && PERSON_TAG_NAME.equals(tagName)) {\n",[48,5928,5929],{"class":50,"line":363},[48,5930,5931],{}," return true;\n",[48,5933,5934],{"class":50,"line":369},[48,5935,5936],{}," } else if (!isStart && PERSONS_TAG_NAME.equals(tagName)) {\n",[48,5938,5939],{"class":50,"line":3187},[48,5940,5941],{}," // end tag of persons, nothing else to handle\n",[48,5943,5944],{"class":50,"line":3193},[48,5945,5946],{}," return false;\n",[48,5948,5949],{"class":50,"line":3199},[48,5950,5951],{}," }\n",[48,5953,5954],{"class":50,"line":3205},[48,5955,5956],{}," break;\n",[48,5958,5959],{"class":50,"line":3211},[48,5960,5961],{}," case XMLEvent.END_DOCUMENT:\n",[48,5963,5964],{"class":50,"line":3217},[48,5965,5966],{}," return false;\n",[48,5968,5969],{"class":50,"line":3223},[48,5970,5971],{}," }\n",[48,5973,5974],{"class":50,"line":3229},[48,5975,5976],{}," isStart = false;\n",[48,5978,5979],{"class":50,"line":3235},[48,5980,5981],{}," }\n",[18,5983,5984],{},[974,5985,5827],{},[18,5987,5988,5989,5992],{},"The implementation of",[275,5990,5991],{},"getFieldValue(JRField field)"," is very simple, because the attribute name is exactly the name that\nis assigned in the Jasper Report document.",[38,5994,5996],{"className":40,"code":5995,"language":42,"meta":43,"style":43},"return xmlStreamReader.getAttributeValue(null, field.getName());\n",[45,5997,5998],{"__ignoreMap":43},[48,5999,6000],{"class":50,"line":51},[48,6001,5995],{},[30,6003,6005],{"id":6004},"brining-all-together","Brining all together",[18,6007,6008],{},"We have now a XML file that contains our test persons and a custom data source that iterates one by one over each\nperson. It is time to see how this improved the report generation time and bringing all pieces together.",[18,6010,5760,6011,6014],{},[974,6012,6013],{},"ReportGenerator"," class accepts the XML source and the template as stream and via an additional flag it is\npossible to switch between the default and the custom data source. A simple Junit test is using this class to run 4\nreport generations and measures the amount of time it needed. Here the result of the Junit test on my local machine:",[18,6016,6017],{},"`Running com.jasperreports.ReportGeneratorTest",[18,6019,6020],{},"INFO ReportGenerator - Created report with default XML data source in 4.136 seconds.",[18,6022,6023],{},"INFO ReportGenerator - Created report with custom datasource in 0.684 seconds.",[18,6025,6026],{},"INFO ReportGenerator - Created report with default XML data source in 21.463 seconds.",[18,6028,6029],{},"INFO ReportGenerator - Created report with custom datasource in 3.495 seconds.",[18,6031,6032],{},"Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 30.267 sec`",[18,6034,6035],{},"The first two results are using a XML source with 100 Persons, the following two are processing 5000 Persons. The custom\ndata source implementation is about 6 times faster than the default implementation and this sample “only” uses only a\nfraction of what we had to process in our project. In fact our worst case scenario mentioned in the beginning is using\n50000 records on multiple tabs and therefore this improvement pays of very fast.",[394,6037,396],{},{"title":43,"searchDepth":57,"depth":57,"links":6039},[6040,6041],{"id":5756,"depth":63,"text":5757},{"id":6004,"depth":63,"text":6005},[404],"2012-08-29T02:40:26","While working on one of my projects we were faced with the problem of creating a report with a big amount of data to\\nshow on multiple Excel tabs (about 50000 entries grouped by different criteria’s). We had a couple of requirements that\\nlead us to choose Jasper Reports as our report generation engine. Other requirements lead us to use XML as data source –\\ne.g. to generate the report on the fly without wasting hard disk space for different languages.","https://synyx.de/blog/big-jasper-reports-with-custom-xml-datasource/",{},"/blog/big-jasper-reports-with-custom-xml-datasource",{"title":5717,"description":5727},"blog/big-jasper-reports-with-custom-xml-datasource",[6051,6052,6053],"custom-datasource","jasper-reports","saxpullparser","While working on one of my projects we were faced with the problem of creating a report with a big amount of data to show on multiple Excel tabs (about…","SYnjblwoql00btIP3Bhd2-4MQoGLcsdaZYWx_o08uoA",{"id":6057,"title":6058,"author":6059,"body":6061,"category":6701,"date":6702,"description":6703,"extension":409,"link":6704,"meta":6705,"navigation":177,"path":6706,"seo":6707,"slug":6065,"stem":6708,"tags":6709,"teaser":6710,"__hash__":6711},"blog/blog/visualize-javascript-code-quality-and-code-coverage-with-sonar.md","Visualize JavaScript code quality and code coverage with Sonar",[6060],"seber",{"type":11,"value":6062,"toc":6692},[6063,6066,6069,6075,6078,6084,6098,6101,6105,6154,6157,6170,6173,6187,6198,6201,6286,6289,6292,6295,6298,6301,6304,6307,6317,6319,6322,6325,6368,6371,6406,6409,6501,6510,6513,6516,6519,6524,6528,6535,6539,6546,6571,6575,6578,6587,6590,6599,6610,6620,6624,6627,6630,6638,6648,6652,6657,6663,6668,6673,6690],[14,6064,6058],{"id":6065},"visualize-javascript-code-quality-and-code-coverage-with-sonar",[18,6067,6068],{},"It is hard to imagine a web project without JavaScript code today. JavaScript is an easy to learn and very performant\nscript language. In the past we have used JavaScript mostly for eye-candy and form validation. Recently we have been\nasked more often to implement complex user interfaces with trees, sortable tables and things like that. So we decided to\nrely more on JavaScript to improve the feedback of the website to user actions.",[18,6070,6071,6072],{},"The first question that came up was: ",[974,6073,6074],{},"How to develop test driven with JavaScript?",[18,6076,6077],{},"We decided to use Jasmine, a behaviour driven development framework which tests can be run headless in a Maven build for\nexample.",[18,6079,6080,6081],{},"The second question was: ",[974,6082,6083],{},"How to visualise code coverage and code quality?",[18,6085,6086,6087,6093,6094,6097],{},"The tool Sonar has been proven to be useful in our Java projects in the past. So the first I was searching for was the\nJavaScript Plugin for Sonar. It can be\ndownloaded ",[22,6088,6092],{"href":6089,"rel":6090,"title":6091},"https://web.archive.org/web/20150530172810/http://docs.codehaus.org/display/SONAR/JavaScript+Plugin",[26],"Sonar JavaScript Plugin","here","\nand was luckily updated to version 1.0 recently with a bunch of new metrics like “",[275,6095,6096],{},"avoid usage of == and !=","”.",[18,6099,6100],{},"Unfortunately this plugin only supports JsTestDriver for code coverage and other test metrics. However, Jasmine support\nis on the Roadmap and I’m looking forward to see the next release of the JavaScript Plugin. But at the moment I had to\nintegrate our Jasmine and jasmine-jquery tests with JsTestDriver, the JavaScript Plugin of Sonar and an automated maven\nbuild.",[1687,6102,6104],{"id":6103},"used-technologies","Used technologies",[868,6106,6107,6114,6121,6128,6135,6142,6149],{},[871,6108,6109],{},[22,6110,6113],{"href":6111,"rel":6112,"title":6113},"https://maven.apache.org/",[26],"Maven",[871,6115,6116],{},[22,6117,6120],{"href":6118,"rel":6119,"title":6120},"https://github.com/jasmine/jasmine",[26],"Jasmine",[871,6122,6123],{},[22,6124,6127],{"href":6125,"rel":6126,"title":6127},"https://github.com/ibolmo/jasmine-jstd-adapter",[26],"jasmine-jstd-adapter",[871,6129,6130],{},[22,6131,6134],{"href":6132,"rel":6133,"title":6134},"https://code.google.com/p/js-test-driver/",[26],"JsTestDriver",[871,6136,6137],{},[22,6138,6141],{"href":6139,"rel":6140,"title":6141},"https://code.google.com/p/jstd-maven-plugin/",[26],"jstd-maven-plugin",[871,6143,6144],{},[22,6145,6148],{"href":6146,"rel":6147,"title":6148},"https://sonarsource.com/",[26],"Sonar",[871,6150,6151],{},[22,6152,6091],{"href":6089,"rel":6153,"title":6091},[26],[1687,6155,6134],{"id":6156},"jstestdriver",[18,6158,6159,6160,6164,6165,392],{},"JsTestDriver is a test runner designed by Google and can be\ndownloaded ",[22,6161,6092],{"href":6162,"rel":6163,"title":6134},"http://code.google.com/p/js-test-driver/downloads/",[26],". If you don’t know JSTestDriver\nyet, you maybe want to run over\nit’s ",[22,6166,2091],{"href":6167,"rel":6168,"title":6169},"http://code.google.com/p/js-test-driver/w/list",[26],"JsTestDriver Documentation",[18,6171,6172],{},"Some advantages of JsTestDriver:",[868,6174,6175,6178,6181,6184],{},[871,6176,6177],{},"Eclipse and IntelliJ integration",[871,6179,6180],{},"Maven Plugin",[871,6182,6183],{},"parallel test executions across browsers (local or remote)",[871,6185,6186],{},"code coverage",[18,6188,6189,6190,6193,6194,6197],{},"In order to run JsTestDriver you have to create a config file. By default you have to name it ",[275,6191,6192],{},"jsTestDriver.conf"," and\nyou have to save it in ",[275,6195,6196],{},"src/test/resources",". If you want to choose another filename or path remember to define these in\nthe Maven plugin later.",[18,6199,6200],{},"In the config file you have to define following flags (Be sure that there are no whitespaces in front of the keywords):",[38,6202,6204],{"className":2193,"code":6203,"language":2195,"meta":43,"style":43},"server: http://localhost:9876\nload:\n # jasmine dependency\n - lib/jasmine.js\n # to make our jasmine tests work within jstd\n # (must be included after jasmine.js)\n - lib/jasmineAdapter.js\n # models, views and other stuff\n - src/main/js/*.js\ntest:\n # load all test files\n - src/test/js/*Test.js\nplugin:\n - name: \"coverage\"\n jar: \"lib/coverage-1.3.4.b.jar\"\n module: \"com.google.jstestdriver.coverage.CoverageModule\"\n",[45,6205,6206,6211,6216,6221,6226,6231,6236,6241,6246,6251,6256,6261,6266,6271,6276,6281],{"__ignoreMap":43},[48,6207,6208],{"class":50,"line":51},[48,6209,6210],{},"server: http://localhost:9876\n",[48,6212,6213],{"class":50,"line":57},[48,6214,6215],{},"load:\n",[48,6217,6218],{"class":50,"line":63},[48,6219,6220],{}," # jasmine dependency\n",[48,6222,6223],{"class":50,"line":69},[48,6224,6225],{}," - lib/jasmine.js\n",[48,6227,6228],{"class":50,"line":75},[48,6229,6230],{}," # to make our jasmine tests work within jstd\n",[48,6232,6233],{"class":50,"line":81},[48,6234,6235],{}," # (must be included after jasmine.js)\n",[48,6237,6238],{"class":50,"line":124},[48,6239,6240],{}," - lib/jasmineAdapter.js\n",[48,6242,6243],{"class":50,"line":129},[48,6244,6245],{}," # models, views and other stuff\n",[48,6247,6248],{"class":50,"line":204},[48,6249,6250],{}," - src/main/js/*.js\n",[48,6252,6253],{"class":50,"line":210},[48,6254,6255],{},"test:\n",[48,6257,6258],{"class":50,"line":216},[48,6259,6260],{}," # load all test files\n",[48,6262,6263],{"class":50,"line":357},[48,6264,6265],{}," - src/test/js/*Test.js\n",[48,6267,6268],{"class":50,"line":363},[48,6269,6270],{},"plugin:\n",[48,6272,6273],{"class":50,"line":369},[48,6274,6275],{}," - name: \"coverage\"\n",[48,6277,6278],{"class":50,"line":3187},[48,6279,6280],{}," jar: \"lib/coverage-1.3.4.b.jar\"\n",[48,6282,6283],{"class":50,"line":3193},[48,6284,6285],{}," module: \"com.google.jstestdriver.coverage.CoverageModule\"\n",[635,6287,6288],{"id":6288},"server",[18,6290,6291],{},"JsTestDriver starts it’s own server and generates a HTML page that can be captured by various browsers.",[635,6293,6294],{"id":6294},"load",[18,6296,6297],{},"Define all needed JavaScript files like your models and views and so on. You can use a wildcard * to include all files\nwithin the specified directory. Note that it could be relevant to load your files in an correct order since a normal\nHTML page will be created and some dependencies have to be considered. The load sequence will be alphabetically if the\nwildcard is used.",[635,6299,6300],{"id":6300},"test",[18,6302,6303],{},"simply attaches the test files to the created HTML page.",[635,6305,6306],{"id":6306},"plugin",[18,6308,6309,6310,6316],{},"to be able to see the code coverage report in Sonar you have to download\nthe ",[22,6311,6315],{"href":6312,"rel":6313,"title":6314},"http://code.google.com/p/js-test-driver/downloads/list",[26],"jstd coverage plugin","coverage plugin"," and save it\nsomewhere as you wish. Just remember to add the path to the plugin jar flag as shown in the listing above.",[1687,6318,6141],{"id":6141},[18,6320,6321],{},"Before we can see the Sonar report about the code quality and code coverage we have to configure maven to run jstd.",[18,6323,6324],{},"Unfortunately, the jstd-maven-plugin is not available at the Maven Central Repository. Therefore we have to add a new\nrepository and pluginRepository to our pom.xml:",[38,6326,6328],{"className":2193,"code":6327,"language":2195,"meta":43,"style":43},"\u003Crepository>\n \u003Cid>jstd-maven-plugin google code repo\u003C/id>\n \u003Curl>http://jstd-maven-plugin.googlecode.com/svn/maven2\u003C/url>\n\u003C/repository>\n\u003CpluginRepository>\n \u003Cid>jstd-maven-plugin google code repo\u003C/id>\n \u003Curl>http://jstd-maven-plugin.googlecode.com/svn/maven2\u003C/url>\n\u003C/pluginRepository>\n",[45,6329,6330,6335,6340,6345,6350,6355,6359,6363],{"__ignoreMap":43},[48,6331,6332],{"class":50,"line":51},[48,6333,6334],{},"\u003Crepository>\n",[48,6336,6337],{"class":50,"line":57},[48,6338,6339],{}," \u003Cid>jstd-maven-plugin google code repo\u003C/id>\n",[48,6341,6342],{"class":50,"line":63},[48,6343,6344],{}," \u003Curl>http://jstd-maven-plugin.googlecode.com/svn/maven2\u003C/url>\n",[48,6346,6347],{"class":50,"line":69},[48,6348,6349],{},"\u003C/repository>\n",[48,6351,6352],{"class":50,"line":75},[48,6353,6354],{},"\u003CpluginRepository>\n",[48,6356,6357],{"class":50,"line":81},[48,6358,6339],{},[48,6360,6361],{"class":50,"line":124},[48,6362,6344],{},[48,6364,6365],{"class":50,"line":129},[48,6366,6367],{},"\u003C/pluginRepository>\n",[18,6369,6370],{},"After that maven should be able to fetch the jstd-maven-plugin artifact:",[38,6372,6374],{"className":2193,"code":6373,"language":2195,"meta":43,"style":43},"\u003Cdependency>\n \u003CgroupId>com.googlecode.jstd-maven-plugin\u003C/groupId>\n \u003CartifactId>jstd-maven-plugin\u003C/artifactId>\n \u003Cversion>1.3.2.5\u003C/version>\n \u003Cscope>test\u003C/scope>\n\u003C/dependency>\n",[45,6375,6376,6381,6386,6391,6396,6401],{"__ignoreMap":43},[48,6377,6378],{"class":50,"line":51},[48,6379,6380],{},"\u003Cdependency>\n",[48,6382,6383],{"class":50,"line":57},[48,6384,6385],{}," \u003CgroupId>com.googlecode.jstd-maven-plugin\u003C/groupId>\n",[48,6387,6388],{"class":50,"line":63},[48,6389,6390],{}," \u003CartifactId>jstd-maven-plugin\u003C/artifactId>\n",[48,6392,6393],{"class":50,"line":69},[48,6394,6395],{}," \u003Cversion>1.3.2.5\u003C/version>\n",[48,6397,6398],{"class":50,"line":75},[48,6399,6400],{}," \u003Cscope>test\u003C/scope>\n",[48,6402,6403],{"class":50,"line":81},[48,6404,6405],{},"\u003C/dependency>\n",[18,6407,6408],{},"To run our tests with a maven build we need the jstd-maven-plugin as a Maven plugin:",[38,6410,6412],{"className":2193,"code":6411,"language":2195,"meta":43,"style":43},"\u003Cplugin>\n \u003CgroupId>com.googlecode.jstd-maven-plugin\u003C/groupId>\n \u003CartifactId>jstd-maven-plugin\u003C/artifactId>\n \u003Cversion>1.3.2.5\u003C/version>\n \u003Cconfiguration>\n \u003Cbrowser>firefox\u003C/browser>\n \u003Cport>9876\u003C/port>\n \u003CtestOutput>target/jstestdriver\u003C/testOutput>\n \u003C/configuration>\n \u003Cexecutions>\n \u003Cexecution>\n \u003Cid>run-tests\u003C/id>\n \u003Cgoals>\n \u003Cgoal>test\u003C/goal>\n \u003C/goals>\n \u003C/execution>\n \u003C/executions>\n\u003C/plugin>\n",[45,6413,6414,6419,6423,6427,6431,6436,6441,6446,6451,6456,6461,6466,6471,6476,6481,6486,6491,6496],{"__ignoreMap":43},[48,6415,6416],{"class":50,"line":51},[48,6417,6418],{},"\u003Cplugin>\n",[48,6420,6421],{"class":50,"line":57},[48,6422,6385],{},[48,6424,6425],{"class":50,"line":63},[48,6426,6390],{},[48,6428,6429],{"class":50,"line":69},[48,6430,6395],{},[48,6432,6433],{"class":50,"line":75},[48,6434,6435],{}," \u003Cconfiguration>\n",[48,6437,6438],{"class":50,"line":81},[48,6439,6440],{}," \u003Cbrowser>firefox\u003C/browser>\n",[48,6442,6443],{"class":50,"line":124},[48,6444,6445],{}," \u003Cport>9876\u003C/port>\n",[48,6447,6448],{"class":50,"line":129},[48,6449,6450],{}," \u003CtestOutput>target/jstestdriver\u003C/testOutput>\n",[48,6452,6453],{"class":50,"line":204},[48,6454,6455],{}," \u003C/configuration>\n",[48,6457,6458],{"class":50,"line":210},[48,6459,6460],{}," \u003Cexecutions>\n",[48,6462,6463],{"class":50,"line":216},[48,6464,6465],{}," \u003Cexecution>\n",[48,6467,6468],{"class":50,"line":357},[48,6469,6470],{}," \u003Cid>run-tests\u003C/id>\n",[48,6472,6473],{"class":50,"line":363},[48,6474,6475],{}," \u003Cgoals>\n",[48,6477,6478],{"class":50,"line":369},[48,6479,6480],{}," \u003Cgoal>test\u003C/goal>\n",[48,6482,6483],{"class":50,"line":3187},[48,6484,6485],{}," \u003C/goals>\n",[48,6487,6488],{"class":50,"line":3193},[48,6489,6490],{}," \u003C/execution>\n",[48,6492,6493],{"class":50,"line":3199},[48,6494,6495],{}," \u003C/executions>\n",[48,6497,6498],{"class":50,"line":3205},[48,6499,6500],{},"\u003C/plugin>\n",[18,6502,6503,6504,6509],{},"Three configuration flags are mandatory. More command line flags can be found in\nthe ",[22,6505,2091],{"href":6506,"rel":6507,"title":6508},"http://code.google.com/p/js-test-driver/wiki/CommandLineFlags",[26],"jstd-maven-plugin documentation"," of\njstd.",[635,6511,6512],{"id":6512},"browser",[18,6514,6515],{},"a comma separated list of browsers (more exactly the path to the specific browser) that should be used for the tests",[635,6517,6518],{"id":6518},"port",[18,6520,6521,6522],{},"the port that is set in ",[275,6523,6192],{},[635,6525,6527],{"id":6526},"testoutput","testOutput",[18,6529,6530,6531,6534],{},"This specifies the directory where the code coverage reports (needed for Sonar) will be saved. The default directory for\nsonar is ",[275,6532,6533],{},"target/jstestdriver",", so remember to configure sonar accordingly, if you choose another directory.",[1687,6536,6538],{"id":6537},"set-the-sourcedirectory-in-the-pomxml","Set the sourceDirectory in the pom.xml",[18,6540,6541,6542,6545],{},"In order for Sonar to be able to analyze the JavaScript code and to visualize the reports, we must add the path to the\nsource code which is ",[275,6543,6544],{},"src/main/js"," in our case.",[38,6547,6549],{"className":2193,"code":6548,"language":2195,"meta":43,"style":43},"\u003Cbuild>\n \u003CsourceDirectory>src/main/js\u003C/sourceDirectory>\n \u003C!-- ... -->\n\u003C/build>\n",[45,6550,6551,6556,6561,6566],{"__ignoreMap":43},[48,6552,6553],{"class":50,"line":51},[48,6554,6555],{},"\u003Cbuild>\n",[48,6557,6558],{"class":50,"line":57},[48,6559,6560],{}," \u003CsourceDirectory>src/main/js\u003C/sourceDirectory>\n",[48,6562,6563],{"class":50,"line":63},[48,6564,6565],{}," \u003C!-- ... -->\n",[48,6567,6568],{"class":50,"line":69},[48,6569,6570],{},"\u003C/build>\n",[1687,6572,6574],{"id":6573},"run-the-tests-and-the-analysis","Run the tests and the analysis",[18,6576,6577],{},"Everything should be configured correctly now. So just start the maven build:",[38,6579,6581],{"className":2193,"code":6580,"language":2195,"meta":43,"style":43},"mvn jstd:test\n",[45,6582,6583],{"__ignoreMap":43},[48,6584,6585],{"class":50,"line":51},[48,6586,6580],{},[18,6588,6589],{},"JsTestDriver opens the defined browsers, runs all tests and generates the code coverage report. After that we have to\nstart the sonar build:",[38,6591,6593],{"className":2193,"code":6592,"language":2195,"meta":43,"style":43},"mvn sonar:sonar -Dsonar.language=js -Dsonar.branch=js\n",[45,6594,6595],{"__ignoreMap":43},[48,6596,6597],{"class":50,"line":51},[48,6598,6592],{},[18,6600,6601,6602,6605,6606,6609],{},"To tell sonar to analyze a JavaScript project the ",[275,6603,6604],{},"sonar.language"," property is essential. If the same project should be\nanalyzed as a Java project you may want to add a branch with the property ",[275,6607,6608],{},"sonar.branch",". Otherwise the previous values\nwill be overridden with this JavaScript analysis.",[18,6611,6612,6616,6617],{},[1195,6613],{"alt":6614,"src":6615},"\"JavaScript Plugin - Sonar\"","https://media.synyx.de/uploads//2012/08/js_sonar_01.png"," ",[1195,6618],{"alt":6614,"src":6619},"https://media.synyx.de/uploads//2012/08/js_sonar_02.png",[1687,6621,6623],{"id":6622},"problems","Problems",[18,6625,6626],{},"An annoying problem is running the tests with real browsers like Firefox and Chrome. The maven build automatically\nstarts the browser and also closes it after the tests are finished. But Firefox is not correctly closed by jstd somehow…\nso the next test run fails because Firefox opens a dialog which must be closed manually. The maven build is deadlocked\nand you have to abort and rerun it…",[18,6628,6629],{},"So maybe a running Firefox process would be a workaround, I thought. Well, it kinda worked but the opened tab was not\nclosed anymore (tested on Linux and Windows). Each new test run opened a new tab and after a handful testruns the tests\nfailed because of some strange error. Closing tabs manually solved this, however. Same problem occurred with Chrome (\nVersion 22.0.1201.0 dev).",[18,6631,6632,6633,6637],{},"On one hand it is really nice to run the tests in all desired browsers, on the other hand closing tabs/browsers manually\nmakes it impossible to automate this process. So I’m really looking forward to Jasmine support of the sonar JavaScript\nPlugin to run headless tests as a maven build, just like jasmine-maven-plugin. A quick google search links to this\nproject: ",[22,6634,6635],{"href":6635,"rel":6636},"https://github.com/jwark/jstd-standalone-headless",[26]," Maybe this could be a solution… Any information is welcome,\nso if you have a working setup, please let me know.",[18,6639,6640,6641,6644,6645,6647],{},"Another problem surely is the mandatory specification of the ",[275,6642,6643],{},"sourceDirectory"," to be able to see the metrics in Sonar.\nUsually you will have a Java project with some JavaScript code. Therefore you certainly can’t pinpoint to ",[275,6646,6544],{},"\nas source directory of the project, for example. Further information is appreciated, again 🙂",[1687,6649,6651],{"id":6650},"todo","Todo",[18,6653,6654],{},[974,6655,6656],{},"automate the analysis within a Jenkins build process",[18,6658,6659,6660],{},"— ",[275,6661,6662],{},"maybe jstd tests can be run headless?",[18,6664,6659,6665],{},[275,6666,6667],{},"maybe maven profiles could be used to prevent the sourceDirectory declaration?",[18,6669,6670],{},[974,6671,6672],{},"require.js integration in jstd-unit-tests",[18,6674,6659,6675],{},[275,6676,6677,6683,6684,6689],{},[22,6678,6682],{"href":6679,"rel":6680,"title":6681},"http://requirejs.org/",[26],"require.js","RequireJS"," is a JavaScript file and module loader\nand ",[22,6685,6688],{"href":6686,"rel":6687},"https://github.com/podefr/jasmine-reqjs-jstd/wiki/how-to-setup-requirejs---jasmine---jsTestDriver",[26],"this"," should be\na good starting point.",[394,6691,396],{},{"title":43,"searchDepth":57,"depth":57,"links":6693},[6694,6695,6696,6697,6698,6699,6700],{"id":6103,"depth":57,"text":6104},{"id":6156,"depth":57,"text":6134},{"id":6141,"depth":57,"text":6141},{"id":6537,"depth":57,"text":6538},{"id":6573,"depth":57,"text":6574},{"id":6622,"depth":57,"text":6623},{"id":6650,"depth":57,"text":6651},[403,404,406],"2012-08-08T13:43:42","It is hard to imagine a web project without JavaScript code today. JavaScript is an easy to learn and very performant\\nscript language. In the past we have used JavaScript mostly for eye-candy and form validation. Recently we have been\\nasked more often to implement complex user interfaces with trees, sortable tables and things like that. So we decided to\\nrely more on JavaScript to improve the feedback of the website to user actions.","https://synyx.de/blog/visualize-javascript-code-quality-and-code-coverage-with-sonar/",{},"/blog/visualize-javascript-code-quality-and-code-coverage-with-sonar",{"title":6058,"description":6068},"blog/visualize-javascript-code-quality-and-code-coverage-with-sonar",[],"It is hard to imagine a web project without JavaScript code today. JavaScript is an easy to learn and very performant script language. In the past we have used JavaScript…","mrqNn4n0IH3ZbUdfxIC3kySm1Vw9wOmXI1qcURunod0",{"id":6713,"title":6714,"author":6715,"body":6716,"category":7043,"date":7044,"description":7045,"extension":409,"link":7046,"meta":7047,"navigation":177,"path":7048,"seo":7049,"slug":6720,"stem":7050,"tags":7051,"teaser":7055,"__hash__":7056},"blog/blog/make-software-projects-fit-for-git.md","Make software-projects fit for git",[5633],{"type":11,"value":6717,"toc":7041},[6718,6721,6724,6730,6735,6758,6761,6767,6772,6782,6788,6793,6796,6830,6835,6838,6867,6870,6900,6903,6906,6979,6982,6985,6990,6993,6996,6999,7029,7032,7035,7038],[14,6719,6714],{"id":6720},"make-software-projects-fit-for-git",[18,6722,6723],{},"More and more Projects at our company are taking advantage of distributed and local revision control by using git. So to\nmake a complete software-project fit for git, by not only using git-svn with subversion and git on top, some more\nsteps are required than just handling files with git, learning its syntax and understanding the way it works…",[18,6725,6726],{},[1195,6727],{"alt":6728,"src":6729},"\"git-logo\"","https://media.synyx.de/uploads//2011/10/git-logo.png",[18,6731,6732,392],{},[275,6733,6734],{},"Source code has to be accessible",[18,6736,6737,6738,6744,6745,6751,6752,6757],{},"We are used to use subversion, a central repository with the leading stage of developement, when using git – all\nrepositories are equal. To take the best of both worlds we host a git-repository, which is defined to be leading (only\nby convention). We like to have things under control, so we\nuse ",[22,6739,6743],{"href":6740,"rel":6741,"title":6742},"http://eagain.net/gitweb/?p=gitosis.git",[26],"Gitosis download","gitosis"," to serve these repositories, but we think\nabout using ",[22,6746,6750],{"href":6747,"rel":6748,"title":6749},"https://github.com/sitaramc/gitolite/wiki",[26],"gitolite on GitHub","gitolite"," because of better/easier\naccess-management. You can also host at ",[22,6753,1791],{"href":6754,"rel":6755,"title":6756},"https://github.com/",[26],"Github",", they do great work and it´s their daily\nbusiness.",[18,6759,6760],{},"What else do we need to develop an amazing piece of software in addition to good code and a working methodology? Which\ntools assist the development process and need capability to handle git-repositories?",[18,6762,6763],{},[1195,6764],{"alt":6765,"src":6766},"\"chiliproject-logo\"","https://media.synyx.de/uploads//2011/10/chiliproject-logo.png",[18,6768,6769,392],{},[275,6770,6771],{},"Software should do what it is intended for",[18,6773,6774,6775,6781],{},"To reach this goal we collect production requirements and fragment the subsequent work into processable packets with\na *\n*project-management tool** called redmine, more precisely ",[22,6776,6780],{"href":6777,"rel":6778,"title":6779},"https://www.chiliproject.org/",[26],"ChiliProject","**chiliproject\n**",", an rapidly evolving fork of redmine.",[18,6783,6784],{},[1195,6785],{"alt":6786,"src":6787},"\"jenkins_logo\"","https://media.synyx.de/uploads//2011/10/jenkins_logo.png",[18,6789,6790,489],{},[275,6791,6792],{},"Software is something executable",[18,6794,6795],{},"plain source-code is for documentation purposes 😉",[18,6797,6798,6799,6804,6805,6808,6809,6815,6816,6822,6823,6829],{},"We have to build it. Most of our projects are written in Java and built\nwith ",[22,6800,6803],{"href":6801,"rel":6802,"title":6113},"http://maven.apache.org/",[26],"Apache Maven",". To build the written code automatically and pursue the process of\n",[974,6806,6807],{},"continuous integration"," we utilize a tool named hudson, more precisely ",[22,6810,6814],{"href":6811,"rel":6812,"title":6813},"http://jenkins-ci.org/",[26],"Jenkins","**Jenkins\n**",", an Oracle-independent fork (yeah we like using forks, especially when main\ndevelopers from the origin project are switching to the new fork, if you are interested in all of our reasons read\nthe ",[22,6817,6821],{"href":6818,"rel":6819,"title":6820},"http://blog.synyx.de/2011/05/opensource-is-not-just-about-the-license/",[26],"opensource is not just about the license","blogpost","\nwritten by ",[22,6824,6828],{"href":6825,"rel":6826,"title":6827},"http://blog.synyx.de/autoren/?uid=14",[26],"Fabian Buch","Fabian",")",[18,6831,6832],{},[974,6833,6834],{},"So first mission is to make ChiliProject fit for git.",[18,6836,6837],{},"Luckily ChiliProject can handle git-repositories out of the box, but the repositories have to be cloned to localhost(\nthe machine running chiliproject). This can be achieved by giving read-rights to the user running chiliproject, in our\ncase this is generating a passwordless ssh-keypair, deploy the public part of it to gitosis and explicitly give rights\nto this public-key. To use the generated private-key every time we use git (in conjunction with ssh) we have to modify\nthe file ~/.ssh/config:",[38,6839,6841],{"className":458,"code":6840,"language":460,"meta":43,"style":43},"Host git.domain.tld\nUser git\nIdentityFile ~/.ssh/git_key.priv\n",[45,6842,6843,6851,6859],{"__ignoreMap":43},[48,6844,6845,6848],{"class":50,"line":51},[48,6846,6847],{"class":467},"Host",[48,6849,6850],{"class":475}," git.domain.tld\n",[48,6852,6853,6856],{"class":50,"line":57},[48,6854,6855],{"class":467},"User",[48,6857,6858],{"class":475}," git\n",[48,6860,6861,6864],{"class":50,"line":63},[48,6862,6863],{"class":467},"IdentityFile",[48,6865,6866],{"class":475}," ~/.ssh/git_key.priv\n",[18,6868,6869],{},"Now we need to clone the repository manually by login to the machine running Chili and do:",[38,6871,6873],{"className":458,"code":6872,"language":460,"meta":43,"style":43},"mkdir /path/to/git/repositories/\ncd /path/to/git/repositories/\ngit clone git@gitosis.domain.tld:gitrepo.git\n",[45,6874,6875,6883,6890],{"__ignoreMap":43},[48,6876,6877,6880],{"class":50,"line":51},[48,6878,6879],{"class":467},"mkdir",[48,6881,6882],{"class":475}," /path/to/git/repositories/\n",[48,6884,6885,6888],{"class":50,"line":57},[48,6886,6887],{"class":471},"cd",[48,6889,6882],{"class":475},[48,6891,6892,6895,6897],{"class":50,"line":63},[48,6893,6894],{"class":467},"git",[48,6896,5265],{"class":475},[48,6898,6899],{"class":475}," git@gitosis.domain.tld:gitrepo.git\n",[18,6901,6902],{},"for sure git has to be installed on the server running Chili. And the repository already exists…",[18,6904,6905],{},"but how do we keep this cloned repository up to date? We solved this by installing a cronjob running as the user,\nrunning Chili, every 5 minutes:",[38,6907,6909],{"className":458,"code":6908,"language":460,"meta":43,"style":43},"*/5 * * * * for i in /path/to/git/repositories/*/; do cd $i && git fetch; git reset refs/remotes/origin/master; done >>/dev/null 2>&1\n",[45,6910,6911],{"__ignoreMap":43},[48,6912,6913,6916,6919,6921,6923,6925,6927,6930,6933,6936,6939,6942,6945,6947,6950,6952,6955,6957,6959,6962,6965,6967,6970,6973,6976],{"class":50,"line":51},[48,6914,6915],{"class":500},"*",[48,6917,6918],{"class":482},"/5 ",[48,6920,6915],{"class":500},[48,6922,472],{"class":500},[48,6924,472],{"class":500},[48,6926,472],{"class":500},[48,6928,6929],{"class":500}," for",[48,6931,6932],{"class":482}," i ",[48,6934,6935],{"class":500},"in",[48,6937,6938],{"class":475}," /path/to/git/repositories/*/",[48,6940,6941],{"class":482},"; ",[48,6943,6944],{"class":500},"do",[48,6946,5370],{"class":471},[48,6948,6949],{"class":482}," $i && ",[48,6951,6894],{"class":467},[48,6953,6954],{"class":475}," fetch",[48,6956,6941],{"class":482},[48,6958,6894],{"class":467},[48,6960,6961],{"class":475}," reset",[48,6963,6964],{"class":475}," refs/remotes/origin/master",[48,6966,6941],{"class":482},[48,6968,6969],{"class":500},"done",[48,6971,6972],{"class":500}," >>",[48,6974,6975],{"class":482},"/dev/null ",[48,6977,6978],{"class":500},"2>&1\n",[18,6980,6981],{},"jap, you can log into a file instead of /dev/null, but we trust… 🙂",[18,6983,6984],{},"that´s it you can now add the local repository to your project in ChiliProject, but give full path including the\n“.git”-folder, it is little fussy in this point.",[18,6986,6987],{},[974,6988,6989],{},"Get Jenkins to work with git",[18,6991,6992],{},"First, we have to do the same things done for ChiliProject, install the git-binary on the system running Jenkins,\ngenerate ssh-keypair, give read-rights to the user(possible stumbling block: we are running jenkins in a\njava-servlet-container so it´s the user running this container!)",[18,6994,6995],{},"modify ~/.ssh/config. Now we should be able to manually clone the targeted repositories, but that´s not what we want (\nremember automatically and continous integration?)",[18,6997,6998],{},"In order to be able to tag the built release version, the user running jenkins needs to give an author to the\ngit-repository, so modify/create ~/.gitconfig of this user:",[38,7000,7002],{"className":458,"code":7001,"language":460,"meta":43,"style":43},"[user]\n name = \"Jenkins\"\n email = \"jenkins@jenkins.domain.tld\"\n",[45,7003,7004,7009,7019],{"__ignoreMap":43},[48,7005,7006],{"class":50,"line":51},[48,7007,7008],{"class":482},"[user]\n",[48,7010,7011,7014,7016],{"class":50,"line":57},[48,7012,7013],{"class":467}," name",[48,7015,663],{"class":475},[48,7017,7018],{"class":475}," \"Jenkins\"\n",[48,7020,7021,7024,7026],{"class":50,"line":63},[48,7022,7023],{"class":467}," email",[48,7025,663],{"class":475},[48,7027,7028],{"class":475}," \"jenkins@jenkins.domain.tld\"\n",[18,7030,7031],{},"Jenkins is not able to handle git by default, we have to install a plugin: login -> Jenkins -> manage Jenkins ->\nmanage plugins -> available -> Git plugin (that´s easy to remember)",[18,7033,7034],{},"After restarting Jenkins you´ll find, under “projectX”/configure -> Source Code Management, the new section git where\nyou can insert the url of your repository -> save",[18,7036,7037],{},"Finally you can build the project(small prayer could help 😉 ) and enjoy the built software and Jenkins´ expandable\nworkflow…",[394,7039,7040],{},"html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}",{"title":43,"searchDepth":57,"depth":57,"links":7042},[],[2375,403,404],"2011-10-25T12:34:45","More and more Projects at our company are taking advantage of distributed and local revision control by using git. So to\\nmake a complete software-project fit for git, by not only using git-svn with subversion and git on top, some more\\nsteps are required than just handling files with git, learning its syntax and understanding the way it works…","https://synyx.de/blog/make-software-projects-fit-for-git/",{},"/blog/make-software-projects-fit-for-git",{"title":6714,"description":6723},"blog/make-software-projects-fit-for-git",[7052,42,7053,5712,7054,2792],"apache","maven","project-management","More and more Projects at our company are taking advantage of distributed and local revision control by using git. So to make a complete software-project fit for git, by not…","vCNC4CoaSUI5ng_rt7Nu-7xypFBFlUaDbA6FV5gZLNA",{"id":7058,"title":7059,"author":7060,"body":7062,"category":7122,"date":7123,"description":7124,"extension":409,"link":7125,"meta":7126,"navigation":177,"path":7127,"seo":7128,"slug":7066,"stem":7130,"tags":7131,"teaser":7132,"__hash__":7133},"blog/blog/solr-as-search-engine-for-opencms.md","Solr as search engine for OpenCms",[7061],"hopf",{"type":11,"value":7063,"toc":7120},[7064,7067,7082,7096,7099,7108,7117],[14,7065,7059],{"id":7066},"solr-as-search-engine-for-opencms",[18,7068,7069,7070,7075,7076,7081],{},"Matching the time of my talk at this years ",[22,7071,7074],{"href":7072,"rel":7073},"http://www.opencms-days.org/en/index.html",[26],"OpenCms Days"," we released our\nmodule for integrating ",[22,7077,7080],{"href":7078,"rel":7079},"https://github.com/synyx/opencms-solr-module",[26],"Solr with OpenCms",". A few days have passed now and\nwe had the time to polish the documentation and some aspects of the module.",[18,7083,7084,7089,7090,7095],{},[22,7085,7088],{"href":7086,"rel":7087},"http://lucene.apache.org/solr/",[26],"Solr"," is a search server that is based on the de facto standard for indexing in\nJava, ",[22,7091,7094],{"href":7092,"rel":7093},"http://lucene.apache.org/",[26],"Apache Lucene",". It provides an abstraction layer above the low level details of\nindexing and adds some useful features like facetting and synonyms.",[18,7097,7098],{},"Solr is integrated transparently as an OpenCms index and can be used and mixed with common Lucene indexes. Communication\nis done via HTTP, Solr is accessed using a REST based interface.",[18,7100,7101,7102,7107],{},"We provide two ways to try the module: You can\neither ",[22,7103,7106],{"href":7104,"rel":7105},"https://github.com/Synyx/opencms-solr-module",[26],"checkout an example application"," that you can start up immediately\nusing the OpenCms demo application TemplateTwo. This is the best place if you want to play with some configuration\noptions and just see how all of it works.",[18,7109,7110,7111,7116],{},"Another way is\nthe ",[22,7112,7115],{"href":7113,"rel":7114},"https://github.com/synyx/opencms-solr-module/wiki/Integrating-Solr-into-an-existing-application",[26],"integration in an existing application which is also described in detail",".\nThis is what you would do if you really want to use it in production.",[18,7118,7119],{},"Please feel free to post any questions or feature requests to the issue tracker.",{"title":43,"searchDepth":57,"depth":57,"links":7121},[],[403,404],"2011-05-26T15:01:54","Matching the time of my talk at this years OpenCms Days we released our\\nmodule for integrating Solr with OpenCms. A few days have passed now and\\nwe had the time to polish the documentation and some aspects of the module.","https://synyx.de/blog/solr-as-search-engine-for-opencms/",{},"/blog/solr-as-search-engine-for-opencms",{"title":7059,"description":7129},"Matching the time of my talk at this years OpenCms Days we released our\nmodule for integrating Solr with OpenCms. A few days have passed now and\nwe had the time to polish the documentation and some aspects of the module.","blog/solr-as-search-engine-for-opencms",[5712,5624,5626],"Matching the time of my talk at this years OpenCms Days we released our module for integrating Solr with OpenCms. A few days have passed now and we had the…","B1O9VoFEtSOcrvIZm-OgWICsh3-nJM9l4WPhJ44dmW8",{"id":7135,"title":7136,"author":7137,"body":7139,"category":7158,"date":7159,"description":7160,"extension":409,"link":7161,"meta":7162,"navigation":177,"path":7163,"seo":7164,"slug":7165,"stem":7166,"tags":7167,"teaser":7175,"__hash__":7176},"blog/blog/opensource-is-not-just-about-the-license.md","Being Open Source instead of just Open-Sourcing or Open Source is not just about the license",[7138],"buch",{"type":11,"value":7140,"toc":7156},[7141,7144,7147,7150],[14,7142,7136],{"id":7143},"being-open-source-instead-of-just-open-sourcing-or-open-source-is-not-just-about-the-license",[18,7145,7146],{},"Open Source is not just about available sources or certain licenses. Successful Open Source projects have a community\nthat matters, not just users, strong leaders that listen and still communicate their vision and goal, growing base of\ncontributors who don’t want to be ignored, even if there’s a benevolent dictator as project lead.",[18,7148,7149],{},"There are some popular Open Source projects which recently failed in some of these areas and got forked. Synyx decided\nto go with the forks even though we are mainly users and in these cases not main contributors. What’s the reason behind\nthese decisions? Our company vision tells us to live Open Source which includes much more than what it looks on its\nsurface. It’s not a goal in itself. We believe openness, communication and trancparency are key to quality software,\nespecially long term. That leads to more deliverable value and improved competitiveness as well as more transparency to\nthe community behind.",[18,7151,7152],{},[1195,7153],{"alt":43,"src":7154,"title":7155},"https://media.synyx.de/uploads//2011/05/chili-300x199.jpg","chili",{"title":43,"searchDepth":57,"depth":57,"links":7157},[],[403,404],"2011-05-20T17:01:44","Open Source is not just about available sources or certain licenses. Successful Open Source projects have a community\\nthat matters, not just users, strong leaders that listen and still communicate their vision and goal, growing base of\\ncontributors who don’t want to be ignored, even if there’s a benevolent dictator as project lead.","https://synyx.de/blog/opensource-is-not-just-about-the-license/",{},"/blog/opensource-is-not-just-about-the-license",{"title":7136,"description":7146},"opensource-is-not-just-about-the-license","blog/opensource-is-not-just-about-the-license",[7168,7169,7170,7171,7172,5712,7173,7174],"chiliproject","community","hudson","jenkins","libreoffice","redmine","transparency","Open Source is not just about available sources or certain licenses. Successful Open Source projects have a community that matters, not just users, strong leaders that listen and still communicate…","CCudIs0-B2Q3HB1MJjr6jXo1c__MAyAy4luOsfGU9SQ",{"id":7178,"title":7179,"author":7180,"body":7181,"category":7312,"date":7313,"description":7314,"extension":409,"link":7315,"meta":7316,"navigation":177,"path":7317,"seo":7318,"slug":7185,"stem":7320,"tags":7321,"teaser":7322,"__hash__":7323},"blog/blog/opencms-days-2011-in-retrospect.md","OpenCms Days 2011 in retrospect",[7061],{"type":11,"value":7182,"toc":7310},[7183,7186,7194,7209,7212,7215,7230,7239,7260,7286,7304,7307],[14,7184,7179],{"id":7185},"opencms-days-2011-in-retrospect",[18,7187,7188,7189,7193],{},"From May 9 2011 to May 10 the ",[22,7190,7192],{"href":7072,"rel":7191},[26],"third OpenCms Days"," took place in Cologne. The\ntopic of the conference was “The OpenCms 8 User Experience”, targeting the release of OpenCms 8 with its advanced direct\nedit (ADE) functionality. We at Synyx, being a sponsor for the third conference in a row, have been looking forward to\nboth of these events, the conference and the release of OpenCms 8 for quite some time. In this blogpost I want to\nmention some of the highlights of the conference, in another blogpost I will describe some of the new features of\nOpenCms 8.",[18,7195,7196,7197,7202,7203,7208],{},"The conference again took place at ",[22,7198,7201],{"href":7199,"rel":7200},"http://www.komed.de/",[26],"KOMED"," which is suited quite well for the amount of people\nthat are attending. There were two tracks, one showcase track where different companies from the community presented\nsolutions they build around OpenCms and a workshop track that was exclusively held\nby ",[22,7204,7207],{"href":7205,"rel":7206},"http://www.alkacon.com/en/",[26],"Alkacon"," employees, mainly targeting new features of OpenCms 8.",[18,7210,7211],{},"The conference started off with the first public presentation of OpenCms 8 in Alexander Kandziors keynote. A lot of\npeople have been looking forward to this moment as the development of the new version was conducted in a private version\ncontrol system so this was the first time to see the new features. The new interface looks really promising and seems to\nbe received well by the audience.",[18,7213,7214],{},"I will not go into detail on the workshop track sessions, the new features of OpenCms will be described in another post.\nIn retrospect I think it was not ideal that on the first day I went to workshop tracks nearly exclusively. All the\nAlkacon team members prepared their slides in a way that makes it easy to take those as a kind of reference manual,\nwhich is good, as you can come back to the slides later and have a look at those to learn the new features.",[18,7216,7217,7218,7223,7224,7229],{},"I heard a lot of good things about the talk on optimizing OpenCms performance using Varnish but that’s one I didn’t\nattend. The single showcase track I went to on the first day was on ",[22,7219,7222],{"href":7220,"rel":7221},"http://www.softwareag.com/",[26],"Software AG"," and the\nmodules they build together with ",[22,7225,7228],{"href":7226,"rel":7227},"http://www.componio.net/",[26],"Componio",". Quite impressive how much work they seem to have\ninvested into implementing a lot of modules and extensions.",[18,7231,7232,7233,7238],{},"The first day ended with the Get-Together at Kandinsky, a restaurant just next to the conference location. The food was\nreally good, a nice location and nice old and new contacts to chat with. Also a big thanks goes out to Alkacon who in\ncelebration of the release of OpenCms 8 supplied us with free (",[22,7234,7237],{"href":7235,"rel":7236},"http://www.gnu.org/philosophy/free-sw.html",[26],"as in beer",")\nbeer :).",[18,7240,7241,7242,7247,7248,7253,7254,7259],{},"On the second day I went only to talks in the showcase track. Selver Softic of ",[22,7243,7246],{"href":7244,"rel":7245},"http://www.infonova.com/",[26],"Infonova","\npresented an Open Source module that they are using for implementing\nthe ",[22,7249,7252],{"href":7250,"rel":7251},"http://telekom.at/",[26],"website of Austrian telekom",". The module makes it possible to\nuse ",[22,7255,7258],{"href":7256,"rel":7257},"http://velocity.apache.org/",[26],"Velocity"," as the templating language for OpenCms. Velocity provides an easier syntax\nthan JSPs and is better suited for a lot of web developers. I am not sure if we will use it in a project in the near\nfuture but it’s often handy to know that something like this is there when you need it.",[18,7261,7262,7263,7268,7269,7274,7275,7280,7281,7285],{},"Another interesting Open Source module was presented by Rich Cooley of ",[22,7264,7267],{"href":7265,"rel":7266},"http://www.northps.com/",[26],"Northpoint Solutions",".\nThe idea behind the module is quite simple but it can be very useful when dealing with large assets. You can declare\nsome assets to reside outside of the Virtual File System which stores its content in the database. The assets are stored\nin the normal filesystem but parts of its content are extracted via the library ",[22,7270,7273],{"href":7271,"rel":7272},"http://tika.apache.org/",[26],"Apache Tika","\nand stored in OpenCms. This is definitively something I will try out in the near future. Also quite interesting that\nthey are also using the search engine Lucene for content aggregation for\nexample ",[22,7276,7279],{"href":7277,"rel":7278},"http://www.chop.edu/",[26],"for the glossary on the website they implemented the module for",". This is something where\nour ",[22,7282,7284],{"href":7078,"rel":7283},[26],"Solr integration"," would probably also be a benefit.",[18,7287,7288,7289,7292,7293,7297,7298,7303],{},"Speaking of Solr, did I miss something? Oh yes, there was also my talk on our integration\nof ",[22,7290,7088],{"href":7086,"rel":7291},[26]," with OpenCms which is\navailable ",[22,7294,7296],{"href":7078,"rel":7295},[26],"as an Open Source module",". Though there have been some\ntechnical difficulties (probably I can refer to those as “the slide incident”) the talk seems to be received really\nwell. A lot of people confirmed that this is an interesting topic that will become more and more important in the\nfuture. I will try to enhance the ",[22,7299,7302],{"href":7300,"rel":7301},"https://github.com/synyx/opencms-solr-module/wiki",[26],"documentation of the module"," in\nthe next days and probably write another blog post going more into some of the details.",[18,7305,7306],{},"Finally, looking at the layout of the conference, I think the separation into workshop and showcase tracks is not as\ngood as in the years before, where the split was between business and technical tracks. A lot of the showcase sessions\nhad a rather technical content so there was no place to go for the business people. Also probably more people would have\nattended the technical showcase talks if they would have been aware that those might also be of interest to them.",[18,7308,7309],{},"All in all the conference was really worthwile as it has been the years before. Alkacon is doing a great job in\norganizing the conference and I hope it will become an annual event.",{"title":43,"searchDepth":57,"depth":57,"links":7311},[],[404],"2011-05-17T14:56:01","From May 9 2011 to May 10 the third OpenCms Days took place in Cologne. The\\ntopic of the conference was “The OpenCms 8 User Experience”, targeting the release of OpenCms 8 with its advanced direct\\nedit (ADE) functionality. We at Synyx, being a sponsor for the third conference in a row, have been looking forward to\\nboth of these events, the conference and the release of OpenCms 8 for quite some time. In this blogpost I want to\\nmention some of the highlights of the conference, in another blogpost I will describe some of the new features of\\nOpenCms 8.","https://synyx.de/blog/opencms-days-2011-in-retrospect/",{},"/blog/opencms-days-2011-in-retrospect",{"title":7179,"description":7319},"From May 9 2011 to May 10 the third OpenCms Days took place in Cologne. The\ntopic of the conference was “The OpenCms 8 User Experience”, targeting the release of OpenCms 8 with its advanced direct\nedit (ADE) functionality. We at Synyx, being a sponsor for the third conference in a row, have been looking forward to\nboth of these events, the conference and the release of OpenCms 8 for quite some time. In this blogpost I want to\nmention some of the highlights of the conference, in another blogpost I will describe some of the new features of\nOpenCms 8.","blog/opencms-days-2011-in-retrospect",[5708,5624,5626],"From May 9 2011 to May 10 the third OpenCms Days took place in Cologne. The topic of the conference was “The OpenCms 8 User Experience”, targeting the release of…","b-YpbhnXuLLNNPkBPQOw0y-8PfoBWh3v0TXYjMdCmWY",{"id":7325,"title":7326,"author":7327,"body":7329,"category":7358,"date":7359,"description":43,"extension":409,"link":7360,"meta":7361,"navigation":177,"path":7362,"seo":7363,"slug":7364,"stem":7365,"tags":7366,"teaser":7369,"__hash__":7370},"blog/blog/open-source-anwendungen-fur-die-community.md","Open Source Anwendungen für die Community",[7328],"karrasz",{"type":11,"value":7330,"toc":7356},[7331,7334,7340,7343,7346,7349],[14,7332,7326],{"id":7333},"open-source-anwendungen-für-die-community",[18,7335,7336],{},[1195,7337],{"alt":7338,"src":7339},"\"Open Source Projekte\"","https://media.synyx.de/uploads//2011/05/opensourceprojekte.jpg",[18,7341,7342],{},"Synyx entwickelt bereits seit Jahren Anwendungen und Programme auf Basis von Open Source. Rund 20 Mitarbeiter\nentwickeln, optimieren und leben Open Source Anwendungen. Denn wer Open Source Solutions programmiert, lebt eine\nPhilosophie.",[18,7344,7345],{},"Einige im Laufe der Zeit selbst entwickelten Tools stellt Synyx der Communitiy wieder zur Verfügung. Darunter sind\nsowohl selbstfinanzierte Entwicklungen als auch Tools die ursprünglich im Kundenauftrag entwickelt wurden und welche von\ndiesen als Dank für die Community frei zugänglich gemacht wurden.",[18,7347,7348],{},"Wir haben auf unserer Homepage alle zur Zeit verfügbaren Anwendungen zusammengestellt. Ihr findet dort unter anderem\nInformationen zu den einzelnen Tools und Links zum Quellcode.",[18,7350,7351],{},[22,7352,7355],{"href":7353,"rel":7354},"https://synyx.de/open-source/",[26],"Link zur Homepage und den Tools",{"title":43,"searchDepth":57,"depth":57,"links":7357},[],[404],"2011-05-04T11:14:29","https://synyx.de/blog/open-source-anwendungen-fur-die-community/",{},"/blog/open-source-anwendungen-fur-die-community",{"title":7326,"description":43},"open-source-anwendungen-fur-die-community","blog/open-source-anwendungen-fur-die-community",[7367,5712,7368],"anwendungen","quellcode","Synyx entwickelt bereits seit Jahren Anwendungen und Programme auf Basis von Open Source. Rund 20 Mitarbeiter entwickeln, optimieren und leben Open Source Anwendungen. Denn wer Open Source Solutions programmiert, lebt…","WON2bBfNFLIuAo91jrjKh7Z6k2_Krd3_mioNFobU70c",{"id":7372,"title":7373,"author":7374,"body":7375,"category":7440,"date":7441,"description":7442,"extension":409,"link":7443,"meta":7444,"navigation":177,"path":7445,"seo":7446,"slug":7379,"stem":7448,"tags":7449,"teaser":7450,"__hash__":7451},"blog/blog/maven-and-opencms.md","Maven and OpenCms",[7061],{"type":11,"value":7376,"toc":7438},[7377,7380,7416,7419],[14,7378,7373],{"id":7379},"maven-and-opencms",[18,7381,7382,7383,7388,7389,7394,7395,7400,7401,7406,7407,7410,7411,392],{},"I ",[22,7384,7387],{"href":7385,"rel":7386},"http://blog.synyx.de/2010/11/netbeans-and-opencms/",[26],"previously mentioned"," that setting up a development environment\nfor ",[22,7390,7393],{"href":7391,"rel":7392},"http://opencms.org/",[26],"OpenCms"," can be quite hard. Besides\nour ",[22,7396,7399],{"href":7397,"rel":7398},"https://github.com/synyx/opencms-netbeans-module",[26],"Netbeans module"," we are using a custom maven plugin for some time\nnow. As we gain a lot of benefit by building our modules from the file system it’s time to release it and see if other\npeople also want to use it. It’s based on an Ant task that has originally been released\nby ",[22,7402,7405],{"href":7403,"rel":7404},"http://www.eurelis.com",[26],"Eurelis",". Today we ",[974,7408,7409],{},"released version 1.0"," which is now available under the terms of\nthe ",[22,7412,7415],{"href":7413,"rel":7414},"http://www.fsf.org/licensing/licenses/lgpl.txt",[26],"GNU Lesser General Public License",[18,7417,7418],{},"The plugin builds OpenCms module zip files from a Maven directory structure and can import these automatically in a\nrunning instance. You don’t have to edit any files in the OpenCms workplace anymore, the local filesystem is the basis\nfor your module. Use the archetype to set up a complete installation of OpenCms 7.5.2 or 7.5.4 in no time.",[18,7420,7421,7422,7426,7427,7432,7433,392],{},"You can find the projects homepage including documentation how to get started and how everything\nworks ",[22,7423,6092],{"href":7424,"rel":7425},"https://github.com/synyx/maven-opencms/",[26],". You should not get problems to get up and running after reading\nthe information from the projects ",[22,7428,7431],{"href":7429,"rel":7430},"https://github.com/synyx/maven-opencms/wiki",[26],"Wiki",". If you’re having any trouble or\nfeature request feel free to contact us or create a ticket in the\nprojects ",[22,7434,7437],{"href":7435,"rel":7436},"https://github.com/synyx/maven-opencms/issues",[26],"issue tracker",{"title":43,"searchDepth":57,"depth":57,"links":7439},[],[403,404],"2011-04-08T17:39:59","I previously mentioned that setting up a development environment\\nfor OpenCms can be quite hard. Besides\\nour Netbeans module we are using a custom maven plugin for some time\\nnow. As we gain a lot of benefit by building our modules from the file system it’s time to release it and see if other\\npeople also want to use it. It’s based on an Ant task that has originally been released\\nby Eurelis. Today we released version 1.0 which is now available under the terms of\\nthe GNU Lesser General Public License.","https://synyx.de/blog/maven-and-opencms/",{},"/blog/maven-and-opencms",{"title":7373,"description":7447},"I previously mentioned that setting up a development environment\nfor OpenCms can be quite hard. Besides\nour Netbeans module we are using a custom maven plugin for some time\nnow. As we gain a lot of benefit by building our modules from the file system it’s time to release it and see if other\npeople also want to use it. It’s based on an Ant task that has originally been released\nby Eurelis. Today we released version 1.0 which is now available under the terms of\nthe GNU Lesser General Public License.","blog/maven-and-opencms",[7053,5624],"I previously mentioned that setting up a development environment for OpenCms can be quite hard. Besides our Netbeans module we are using a custom maven plugin for some time now.…","xHLhHj4ODShymebsyF1zyo6xejQxvqb3ILdPFOcloUA",{"id":7453,"title":7454,"author":7455,"body":7456,"category":7506,"date":7507,"description":7508,"extension":409,"link":7509,"meta":7510,"navigation":177,"path":7511,"seo":7512,"slug":7460,"stem":7514,"tags":7515,"teaser":7516,"__hash__":7517},"blog/blog/solr-summit-frankfurt.md","Solr Summit Frankfurt",[7061],{"type":11,"value":7457,"toc":7504},[7458,7461,7474,7483,7492,7501],[14,7459,7454],{"id":7460},"solr-summit-frankfurt",[18,7462,7463,7464,7469,7470,7473],{},"I just returned\nfrom ",[22,7465,7468],{"href":7466,"rel":7467},"http://www.lucidimagination.com/blog/2011/01/31/solr-summit-series-comes-to-germany-munich23-feb-frankfurt24-feb-2011-2/",[26],"Solr Summit","\nin Frankfurt, a half day mini conference about ",[22,7471,7088],{"href":7086,"rel":7472},[26],", the search server based on Apache\nLucene. It has been a really worthwile event with a lot of insight into large scale implementations of Solr.",[18,7475,7476,7477,7482],{},"The first half of the conference Marc Krellenstein, a Co-Founder\nof ",[22,7478,7481],{"href":7479,"rel":7480},"http://www.lucidimagination.com/",[26],"Lucid Imagination",", presented trends in enterprise search as well as Lucids\ncommercial Solr environment Lucid Works Enterprise. After an outline of the history of search systems he presented\ndifferent characteristics of a successful search system. Though being held by someone who is obviously biased towards\nSolr and Lucene he also summarized where commercial search systems like Autonomy and Fast have their strengths, good to\nhave an insight into competing systems.",[18,7484,7485,7486,7491],{},"Afterwards Oliver Schönherr and Thomas Kwiatkowski spoke on how Solr is used\nat ",[22,7487,7490],{"href":7488,"rel":7489},"http://www.immobilienscout24.de",[26],"Immobilienscout24",", where it powers full text search. Solr had been selected after\nan evaluation period where commercial as well as non-commercial systems were compared. The way Solr is used probably is\nnot a common use case. IS24 uses a custom build search system for doing their structured search, where you basically\nrefine the search results using different form fields. Solr is used to search within this result list by intersecting\nthe Solr search results with the results of the legacy system. They are using a plain Solr 1.4 without any patches and\nonly two additional components, a scheduler for the data import handler that indexes a database and a component that\nprovides fast access to only the ids of documents because that’s all that is needed for the intersection.",[18,7493,7494,7495,7500],{},"The last talk was held by Olaf Zschiedrich of ",[22,7496,7499],{"href":7497,"rel":7498},"https://www.ebay-kleinanzeigen.de/",[26],"eBay Kleinanzeigen",", formerly known\nas Kijiji. eBay Kleinanzeigen seems to use nearly all features that Solr has to offer, most notably facetting,\nautocompletion and more-like-this for displaying related articles. The site is being developed by a relatively small\nteam and seems to be blazing fast though there are lots of hits on Solr, on peak times 1500 requests/s. Of course this\nis only possible as Solr is designed to be scalable by means of its replication features, its internal caching and the\nexternal caching support through ETags. At eBay Kleinanzeigen there are 12 Solr instances that are used for searching\nbut according to Olaf, 8 would still be enough to keep the resource consumption under 50%.",[18,7502,7503],{},"All of the talks were really interesting, Olaf Zschiedrichs being the one with the most laughters. I have learned a lot\nand appreciate the time and costs Lucid Imagination and its partners have invested to make this event possible.",{"title":43,"searchDepth":57,"depth":57,"links":7505},[],[403,404],"2011-02-24T20:34:30","I just returned\\nfrom Solr Summit\\nin Frankfurt, a half day mini conference about Solr, the search server based on Apache\\nLucene. It has been a really worthwile event with a lot of insight into large scale implementations of Solr.","https://synyx.de/blog/solr-summit-frankfurt/",{},"/blog/solr-summit-frankfurt",{"title":7454,"description":7513},"I just returned\nfrom Solr Summit\nin Frankfurt, a half day mini conference about Solr, the search server based on Apache\nLucene. It has been a really worthwile event with a lot of insight into large scale implementations of Solr.","blog/solr-summit-frankfurt",[5708,5626],"I just returned from Solr Summit in Frankfurt, a half day mini conference about Solr, the search server based on Apache Lucene. It has been a really worthwile event with…","kPs7DFsBho3bz4Mub2Pfnm_Wm3cs2gZQU5AYzAkVY8Y",{"id":7519,"title":7520,"author":7521,"body":7523,"category":7579,"date":7580,"description":7581,"extension":409,"link":7582,"meta":7583,"navigation":177,"path":7584,"seo":7585,"slug":7527,"stem":7587,"tags":7588,"teaser":7593,"__hash__":7594},"blog/blog/synyx-messagesource-load-your-i18n-messages-from-database.md","Synyx MessageSource: Load your i18n messages from database",[7522],"kannegiesser",{"type":11,"value":7524,"toc":7577},[7525,7528,7537,7544,7559],[14,7526,7520],{"id":7527},"synyx-messagesource-load-your-i18n-messages-from-database",[18,7529,7530,7531,7536],{},"A while ago we wanted to store internationalisation for a project in database to allow (a subset of) users to create and\nupdate internationalisation using the application itself. When we searched the web for existing projects that allow to\ndo this we did not find a good and ready to use solution. This is why we decided to write the code ourselves and make it\navailable to others, especially since there was some public demand and it will probably not be shipped by SpringSource (\ncheck out ",[22,7532,7535],{"href":7533,"rel":7534},"http://www.google.de/search?q=spring+i18n+database",[26],"Google"," for details).",[18,7538,7539,7540,7543],{},"So today I’d like to announce our new Open Source project ",[974,7541,7542],{},"Synyx Messagesource for Spring"," business-friendly\npublished using Apache License, Version 2.0.",[18,7545,7546,7547,7550,7551,7554,7555,7558],{},"When you want to store internationalisation of your Spring-backed application in database, the project is the right\nthing to use. It provides an implementation of Springs ",[45,7548,7549],{},"MessageSource"," interface that is able to load and cache a set of\nmessages at once using a ",[45,7552,7553],{},"MessageProvider",". The project brings a configurable one that is able to read (and write) your\ni18n to database using JDBC. There is also support to import and export your messages to the “standard” i18n\n",[45,7556,7557],{},".properties"," files.",[18,7560,7421,7561,7565,7566,7571,7572,392],{},[22,7562,6092],{"href":7563,"rel":7564},"http://messagesource.synyx.org",[26],". You should not get problems to get up and running after reading the\ninformation from the ",[22,7567,7570],{"href":7568,"rel":7569},"https://github.com/synyx/messagesource/wiki",[26],"projects Wiki",". If you’re having any trouble or\nfeature request feel free to contact us\nor ",[22,7573,7576],{"href":7574,"rel":7575},"https://github.com/synyx/messagesource/issues",[26],"create a ticket in the projects issue tracker",{"title":43,"searchDepth":57,"depth":57,"links":7578},[],[403,404],"2011-02-14T18:06:55","A while ago we wanted to store internationalisation for a project in database to allow (a subset of) users to create and\\nupdate internationalisation using the application itself. When we searched the web for existing projects that allow to\\ndo this we did not find a good and ready to use solution. This is why we decided to write the code ourselves and make it\\navailable to others, especially since there was some public demand and it will probably not be shipped by SpringSource (\\ncheck out Google for details).","https://synyx.de/blog/synyx-messagesource-load-your-i18n-messages-from-database/",{},"/blog/synyx-messagesource-load-your-i18n-messages-from-database",{"title":7520,"description":7586},"A while ago we wanted to store internationalisation for a project in database to allow (a subset of) users to create and\nupdate internationalisation using the application itself. When we searched the web for existing projects that allow to\ndo this we did not find a good and ready to use solution. This is why we decided to write the code ourselves and make it\navailable to others, especially since there was some public demand and it will probably not be shipped by SpringSource (\ncheck out Google for details).","blog/synyx-messagesource-load-your-i18n-messages-from-database",[7589,7590,7591,7592,5712,420],"database","i18n","internationalisation","internationalization","A while ago we wanted to store internationalisation for a project in database to allow (a subset of) users to create and update internationalisation using the application itself. When we…","nyZcMPq1I7-esYkZoVwAgntWZKJrIJkCdwQvpagdS20",{"id":7596,"title":7597,"author":7598,"body":7599,"category":7649,"date":7650,"description":7651,"extension":409,"link":7652,"meta":7653,"navigation":177,"path":7654,"seo":7655,"slug":7603,"stem":7657,"tags":7658,"teaser":7660,"__hash__":7661},"blog/blog/synyx-open-source-projekt-hades-schafft-den-sprung-zu-springsource.md","Synyx Open Source Projekt Hades schafft den Sprung zu SpringSource",[7328],{"type":11,"value":7600,"toc":7647},[7601,7604,7618,7621,7624,7627,7630],[14,7602,7597],{"id":7603},"synyx-open-source-projekt-hades-schafft-den-sprung-zu-springsource",[18,7605,7606,7607,7612,7613,392],{},"Am Donnerstag hat SpringSource das erste Milestone-Release von Spring Data\nJPA ",[22,7608,7611],{"href":7609,"rel":7610},"http://www.springsource.org/node/3022",[26],"veröffentlicht",". Spring Data JPA ist die Weiterentwicklung der Synyx\nOpenSource ",[22,7614,7617],{"href":7615,"rel":7616},"http://hades.synyx.org",[26],"Bibliothek Hades",[18,7619,7620],{},"Hades wurde hauptsächlich von Oliver Gierke entwickelt, welcher bis Anfang 2010 als Software Architekt bei Synyx tätig\nwar. Die Entwicklung des Projekts wurde von Synyx vollumfänglich unterstützt und gefördert, die Bibliothek in vielen\nProjekten erfolgreich eingesetzt.",[18,7622,7623],{},"Oliver hat mittlerweile neue Wege eingeschlagen und arbeitet nun direkt für SpringSource. Die Entwicklung an Hades\nführte er, auch in Zusammenarbeit mit Synyx, fort. In den letzten Monaten hat er sich darum gekümmert, die Zukunft von\nHades bei SpringSource zu sichern. Deshalb freut es uns natürlich sehr, dass die Bibliothek nun in Spring Data\nintegriert wurde, dort das JPA Modul und darüber hinaus die Basis für die Unterstützung weiterer Persistenztechnologien\nbildet.",[18,7625,7626],{},"Wir hoffen, dass Hades so einer noch breiteren Masse an Entwicklern des Implementieren von Persistenzschichten\nerleichtern wird. Natürlich wird auch Synyx das neue Spring Data JPA mit Vergnügen und Erfolg einsetzen.",[18,7628,7629],{},"Nähere Infos:",[868,7631,7632,7639],{},[871,7633,7634],{},[22,7635,7638],{"href":7636,"rel":7637},"http://synyx.org/",[26],"Synyx.org – Open Source Projekte",[871,7640,7641,7642],{},"Tutorial zu Spring Data JPA von Oliver\nim ",[22,7643,7646],{"href":7644,"rel":7645},"http://blog.springsource.com/2011/02/10/getting-started-with-spring-data-jpa/",[26],"SpringSource Blog",{"title":43,"searchDepth":57,"depth":57,"links":7648},[],[404],"2011-02-13T10:07:31","Am Donnerstag hat SpringSource das erste Milestone-Release von Spring Data\\nJPA veröffentlicht. Spring Data JPA ist die Weiterentwicklung der Synyx\\nOpenSource Bibliothek Hades.","https://synyx.de/blog/synyx-open-source-projekt-hades-schafft-den-sprung-zu-springsource/",{},"/blog/synyx-open-source-projekt-hades-schafft-den-sprung-zu-springsource",{"title":7597,"description":7656},"Am Donnerstag hat SpringSource das erste Milestone-Release von Spring Data\nJPA veröffentlicht. Spring Data JPA ist die Weiterentwicklung der Synyx\nOpenSource Bibliothek Hades.","blog/synyx-open-source-projekt-hades-schafft-den-sprung-zu-springsource",[7659,420],"hades","Am Donnerstag hat SpringSource das erste Milestone-Release von Spring Data JPA veröffentlicht. Spring Data JPA ist die Weiterentwicklung der Synyx OpenSource Bibliothek Hades. Hades wurde hauptsächlich von Oliver Gierke entwickelt,…","0l5QYp6kg1FYAQd1i8BEizzQ0V_uvxv2TDCb_vaCBe0",{"id":7663,"title":7664,"author":7665,"body":7666,"category":8565,"date":8566,"description":8567,"extension":409,"link":8568,"meta":8569,"navigation":177,"path":8570,"seo":8571,"slug":7670,"stem":8573,"tags":8574,"teaser":8575,"__hash__":8576},"blog/blog/scripting-opencms.md","Scripting OpenCms",[7061],{"type":11,"value":7667,"toc":8563},[7668,7671,7684,7693,7705,8076,8079,8181,8184,8207,8210,8233,8236,8241,8244,8557,8560],[14,7669,7664],{"id":7670},"scripting-opencms",[18,7672,7673,7677,7678,7683],{},[22,7674,7393],{"href":7675,"rel":7676},"http://opencms.org/de/",[26]," ships with a shell script for accessing the virtual file system from the command line.\nThis is useful for a lot of administrative tasks like importing modules or exporting content. You can supply scripts\nthat issue commands or use the shell interactively. As the syntax for the scripts is quite limited some tasks can’t be\nachieved that easily. ",[22,7679,7682],{"href":7680,"rel":7681},"http://blog.codecentric.de/en/2010/04/how-to-automate-opencms-module-import/",[26],"This blogpost","\ndescribes a way to circumvent these problems by generating the script files.",[18,7685,7686,7687,7692],{},"I will present a simple extension of this mechanism that makes it possible to access the VFS using\nthe ",[22,7688,7691],{"href":7689,"rel":7690},"https://groovy-lang.org/",[26],"groovy"," scripting language that also runs on the Java Virtual Machine. It can be useful\nto import users or content from different systems, create content for test runs or any other task you can think of.",[18,7694,7695,7696,7699,7700,7704],{},"The original script file for accessing the cms shell is located in ",[45,7697,7698],{},"WEB-INF/cmsshell.sh"," (\nSee ",[22,7701,6092],{"href":7702,"rel":7703},"http://blog.synyx.de/2010/11/using-cmsshell-on-ubuntu-systems/",[26]," on how to make it work on Ubuntu systems).\nThe following file is a modification of the original file that doesn’t call the underlying Java class but another groovy\nscript and should be placed next to the original:",[38,7706,7710],{"className":7707,"code":7708,"language":7709,"meta":43,"style":43},"language-shell shiki shiki-themes github-light github-dark","\n#!/bin/sh\n# Script for evaluating groovy scripts with access to opencms.\n#\n# Please make sure that \"servlet-api.jar\" and \"jsp-api.jar\" are found.\n#\n# get path to opencms base directory\nOPENCMS_BASE=`pwd`\n# get path to tomcat home\nif [ -z \"$TOMCAT_HOME\" ]; then\n [ -n \"$CATALINA_HOME\" ] && TOMCAT_HOME=\"$CATALINA_HOME\"\n [ -z \"$TOMCAT_HOME\" ] && TOMCAT_HOME=\"$OPENCMS_BASE\"/../../..\nfi\nTOMCAT_CLASSPATH=\"\"\n# Support for tomcat 5\nfor JAR in ${TOMCAT_HOME}/common/lib/*.jar; do\n TOMCAT_CLASSPATH=\"${TOMCAT_CLASSPATH}:${JAR}\"\ndone\nfor JAR in ${TOMCAT_HOME}/shared/lib/*.jar; do\n TOMCAT_CLASSPATH=\"${TOMCAT_CLASSPATH}:${JAR}\"\ndone\n# Support for tomcat 6\nfor JAR in ${TOMCAT_HOME}/lib/*.jar; do\n TOMCAT_CLASSPATH=\"${TOMCAT_CLASSPATH}:${JAR}\"\ndone\nOPENCMS_CLASSPATH=\"\"\nfor JAR in ${OPENCMS_BASE}/lib/*.jar; do\n OPENCMS_CLASSPATH=\"${OPENCMS_CLASSPATH}:${JAR}\"\ndone\ngroovy -classpath \"${OPENCMS_CLASSPATH}:${TOMCAT_CLASSPATH}:classes\" evalscripts.groovy -base=\"${OPENCMS_BASE}\" \"$@\"\n\n","shell",[45,7711,7712,7716,7722,7727,7732,7737,7741,7746,7763,7768,7794,7821,7845,7850,7860,7865,7885,7906,7911,7928,7944,7948,7953,7970,7986,7990,7999,8016,8033,8037],{"__ignoreMap":43},[48,7713,7714],{"class":50,"line":51},[48,7715,178],{"emptyLinePlaceholder":177},[48,7717,7718],{"class":50,"line":57},[48,7719,7721],{"class":7720},"sJ8bj","#!/bin/sh\n",[48,7723,7724],{"class":50,"line":63},[48,7725,7726],{"class":7720},"# Script for evaluating groovy scripts with access to opencms.\n",[48,7728,7729],{"class":50,"line":69},[48,7730,7731],{"class":7720},"#\n",[48,7733,7734],{"class":50,"line":75},[48,7735,7736],{"class":7720},"# Please make sure that \"servlet-api.jar\" and \"jsp-api.jar\" are found.\n",[48,7738,7739],{"class":50,"line":81},[48,7740,7731],{"class":7720},[48,7742,7743],{"class":50,"line":124},[48,7744,7745],{"class":7720},"# get path to opencms base directory\n",[48,7747,7748,7751,7754,7757,7760],{"class":50,"line":129},[48,7749,7750],{"class":482},"OPENCMS_BASE",[48,7752,7753],{"class":500},"=",[48,7755,7756],{"class":475},"`",[48,7758,7759],{"class":471},"pwd",[48,7761,7762],{"class":475},"`\n",[48,7764,7765],{"class":50,"line":204},[48,7766,7767],{"class":7720},"# get path to tomcat home\n",[48,7769,7770,7773,7776,7779,7782,7785,7788,7791],{"class":50,"line":210},[48,7771,7772],{"class":500},"if",[48,7774,7775],{"class":482}," [ ",[48,7777,7778],{"class":500},"-z",[48,7780,7781],{"class":475}," \"",[48,7783,7784],{"class":482},"$TOMCAT_HOME",[48,7786,7787],{"class":475},"\"",[48,7789,7790],{"class":482}," ]; ",[48,7792,7793],{"class":500},"then\n",[48,7795,7796,7799,7802,7804,7807,7809,7812,7814,7816,7818],{"class":50,"line":216},[48,7797,7798],{"class":482}," [ ",[48,7800,7801],{"class":500},"-n",[48,7803,7781],{"class":475},[48,7805,7806],{"class":482},"$CATALINA_HOME",[48,7808,7787],{"class":475},[48,7810,7811],{"class":482}," ] && TOMCAT_HOME",[48,7813,7753],{"class":500},[48,7815,7787],{"class":475},[48,7817,7806],{"class":482},[48,7819,7820],{"class":475},"\"\n",[48,7822,7823,7825,7827,7829,7831,7833,7835,7837,7839,7842],{"class":50,"line":357},[48,7824,7798],{"class":482},[48,7826,7778],{"class":500},[48,7828,7781],{"class":475},[48,7830,7784],{"class":482},[48,7832,7787],{"class":475},[48,7834,7811],{"class":482},[48,7836,7753],{"class":500},[48,7838,7787],{"class":475},[48,7840,7841],{"class":482},"$OPENCMS_BASE",[48,7843,7844],{"class":475},"\"/../../..\n",[48,7846,7847],{"class":50,"line":363},[48,7848,7849],{"class":500},"fi\n",[48,7851,7852,7855,7857],{"class":50,"line":369},[48,7853,7854],{"class":482},"TOMCAT_CLASSPATH",[48,7856,7753],{"class":500},[48,7858,7859],{"class":475},"\"\"\n",[48,7861,7862],{"class":50,"line":3187},[48,7863,7864],{"class":7720},"# Support for tomcat 5\n",[48,7866,7867,7869,7872,7874,7877,7880,7882],{"class":50,"line":3193},[48,7868,5515],{"class":500},[48,7870,7871],{"class":482}," JAR ",[48,7873,6935],{"class":500},[48,7875,7876],{"class":482}," ${TOMCAT_HOME}",[48,7878,7879],{"class":475},"/common/lib/*.jar",[48,7881,6941],{"class":482},[48,7883,7884],{"class":500},"do\n",[48,7886,7887,7890,7892,7895,7897,7900,7903],{"class":50,"line":3199},[48,7888,7889],{"class":482}," TOMCAT_CLASSPATH",[48,7891,7753],{"class":500},[48,7893,7894],{"class":475},"\"${",[48,7896,7854],{"class":482},[48,7898,7899],{"class":475},"}:${",[48,7901,7902],{"class":482},"JAR",[48,7904,7905],{"class":475},"}\"\n",[48,7907,7908],{"class":50,"line":3205},[48,7909,7910],{"class":500},"done\n",[48,7912,7913,7915,7917,7919,7921,7924,7926],{"class":50,"line":3211},[48,7914,5515],{"class":500},[48,7916,7871],{"class":482},[48,7918,6935],{"class":500},[48,7920,7876],{"class":482},[48,7922,7923],{"class":475},"/shared/lib/*.jar",[48,7925,6941],{"class":482},[48,7927,7884],{"class":500},[48,7929,7930,7932,7934,7936,7938,7940,7942],{"class":50,"line":3217},[48,7931,7889],{"class":482},[48,7933,7753],{"class":500},[48,7935,7894],{"class":475},[48,7937,7854],{"class":482},[48,7939,7899],{"class":475},[48,7941,7902],{"class":482},[48,7943,7905],{"class":475},[48,7945,7946],{"class":50,"line":3223},[48,7947,7910],{"class":500},[48,7949,7950],{"class":50,"line":3229},[48,7951,7952],{"class":7720},"# Support for tomcat 6\n",[48,7954,7955,7957,7959,7961,7963,7966,7968],{"class":50,"line":3235},[48,7956,5515],{"class":500},[48,7958,7871],{"class":482},[48,7960,6935],{"class":500},[48,7962,7876],{"class":482},[48,7964,7965],{"class":475},"/lib/*.jar",[48,7967,6941],{"class":482},[48,7969,7884],{"class":500},[48,7971,7972,7974,7976,7978,7980,7982,7984],{"class":50,"line":3241},[48,7973,7889],{"class":482},[48,7975,7753],{"class":500},[48,7977,7894],{"class":475},[48,7979,7854],{"class":482},[48,7981,7899],{"class":475},[48,7983,7902],{"class":482},[48,7985,7905],{"class":475},[48,7987,7988],{"class":50,"line":3246},[48,7989,7910],{"class":500},[48,7991,7992,7995,7997],{"class":50,"line":3251},[48,7993,7994],{"class":482},"OPENCMS_CLASSPATH",[48,7996,7753],{"class":500},[48,7998,7859],{"class":475},[48,8000,8001,8003,8005,8007,8010,8012,8014],{"class":50,"line":3256},[48,8002,5515],{"class":500},[48,8004,7871],{"class":482},[48,8006,6935],{"class":500},[48,8008,8009],{"class":482}," ${OPENCMS_BASE}",[48,8011,7965],{"class":475},[48,8013,6941],{"class":482},[48,8015,7884],{"class":500},[48,8017,8018,8021,8023,8025,8027,8029,8031],{"class":50,"line":3261},[48,8019,8020],{"class":482}," OPENCMS_CLASSPATH",[48,8022,7753],{"class":500},[48,8024,7894],{"class":475},[48,8026,7994],{"class":482},[48,8028,7899],{"class":475},[48,8030,7902],{"class":482},[48,8032,7905],{"class":475},[48,8034,8035],{"class":50,"line":3266},[48,8036,7910],{"class":500},[48,8038,8039,8041,8044,8047,8049,8051,8053,8056,8059,8062,8064,8066,8069,8071,8074],{"class":50,"line":3271},[48,8040,7691],{"class":467},[48,8042,8043],{"class":471}," -classpath",[48,8045,8046],{"class":475}," \"${",[48,8048,7994],{"class":482},[48,8050,7899],{"class":475},[48,8052,7854],{"class":482},[48,8054,8055],{"class":475},"}:classes\"",[48,8057,8058],{"class":475}," evalscripts.groovy",[48,8060,8061],{"class":471}," -base=",[48,8063,7894],{"class":475},[48,8065,7750],{"class":482},[48,8067,8068],{"class":475},"}\"",[48,8070,7781],{"class":475},[48,8072,8073],{"class":471},"$@",[48,8075,7820],{"class":475},[18,8077,8078],{},"As you can see, a groovy script named “evalscripts.groovy” is called and all options are passed to it. The script:",[38,8080,8083],{"className":8081,"code":8082,"language":7691,"meta":43,"style":43},"language-groovy shiki shiki-themes github-light github-dark","\nimport org.opencms.main.CmsShell;\nimport org.opencms.file.CmsObject;\nbase = args[0].substring(CmsShell.SHELL_PARAM_BASE.length());\nshell = new CmsShell(base, null, null, \">\", null) {\n CmsObject getCmsObject() {\n return m_cms;\n }\n}\nuser = \"Admin\";\npass = \"admin\";\ncms = shell.getCmsObject();\ncms.loginUser(user, pass);\nbinding1 = new Binding();\nbinding1.setProperty('cmsObject' , cms);\ngroovyShell = new GroovyShell(binding1);\nfor (int i = 1; i \u003C args.length; i++) {\n groovyShell.evaluate(new File(args[i]))\n}\nshell.exit();\n\n",[45,8084,8085,8089,8094,8099,8104,8109,8114,8119,8123,8127,8132,8137,8142,8147,8152,8157,8162,8167,8172,8176],{"__ignoreMap":43},[48,8086,8087],{"class":50,"line":51},[48,8088,178],{"emptyLinePlaceholder":177},[48,8090,8091],{"class":50,"line":57},[48,8092,8093],{},"import org.opencms.main.CmsShell;\n",[48,8095,8096],{"class":50,"line":63},[48,8097,8098],{},"import org.opencms.file.CmsObject;\n",[48,8100,8101],{"class":50,"line":69},[48,8102,8103],{},"base = args[0].substring(CmsShell.SHELL_PARAM_BASE.length());\n",[48,8105,8106],{"class":50,"line":75},[48,8107,8108],{},"shell = new CmsShell(base, null, null, \">\", null) {\n",[48,8110,8111],{"class":50,"line":81},[48,8112,8113],{}," CmsObject getCmsObject() {\n",[48,8115,8116],{"class":50,"line":124},[48,8117,8118],{}," return m_cms;\n",[48,8120,8121],{"class":50,"line":129},[48,8122,261],{},[48,8124,8125],{"class":50,"line":204},[48,8126,266],{},[48,8128,8129],{"class":50,"line":210},[48,8130,8131],{},"user = \"Admin\";\n",[48,8133,8134],{"class":50,"line":216},[48,8135,8136],{},"pass = \"admin\";\n",[48,8138,8139],{"class":50,"line":357},[48,8140,8141],{},"cms = shell.getCmsObject();\n",[48,8143,8144],{"class":50,"line":363},[48,8145,8146],{},"cms.loginUser(user, pass);\n",[48,8148,8149],{"class":50,"line":369},[48,8150,8151],{},"binding1 = new Binding();\n",[48,8153,8154],{"class":50,"line":3187},[48,8155,8156],{},"binding1.setProperty('cmsObject' , cms);\n",[48,8158,8159],{"class":50,"line":3193},[48,8160,8161],{},"groovyShell = new GroovyShell(binding1);\n",[48,8163,8164],{"class":50,"line":3199},[48,8165,8166],{},"for (int i = 1; i \u003C args.length; i++) {\n",[48,8168,8169],{"class":50,"line":3205},[48,8170,8171],{}," groovyShell.evaluate(new File(args[i]))\n",[48,8173,8174],{"class":50,"line":3211},[48,8175,266],{},[48,8177,8178],{"class":50,"line":3217},[48,8179,8180],{},"shell.exit();\n",[18,8182,8183],{},"We start by creating an instance of the CmsShell class and make the underlying CmsObject accessible. We login using the\nAdmin user and bind the instance so we can use it in the scripts that are doing the real work. This is where you come\ninto play: You can write any groovy script that uses this CmsObject and do whatever you want. Some ideas? Why not create\nsome users:",[38,8185,8187],{"className":8081,"code":8186,"language":7691,"meta":43,"style":43},"\n10.times {\n cmsObject.createUser(\"User$it\", \"Pass$it\", \"\", new HashMap());\n}\n\n",[45,8188,8189,8193,8198,8203],{"__ignoreMap":43},[48,8190,8191],{"class":50,"line":51},[48,8192,178],{"emptyLinePlaceholder":177},[48,8194,8195],{"class":50,"line":57},[48,8196,8197],{},"10.times {\n",[48,8199,8200],{"class":50,"line":63},[48,8201,8202],{}," cmsObject.createUser(\"User$it\", \"Pass$it\", \"\", new HashMap());\n",[48,8204,8205],{"class":50,"line":69},[48,8206,266],{},[18,8208,8209],{},"Or list all users:",[38,8211,8213],{"className":8081,"code":8212,"language":7691,"meta":43,"style":43},"\ncmsObject.getUsers().each {\n println it.name\n}\n\n",[45,8214,8215,8219,8224,8229],{"__ignoreMap":43},[48,8216,8217],{"class":50,"line":51},[48,8218,178],{"emptyLinePlaceholder":177},[48,8220,8221],{"class":50,"line":57},[48,8222,8223],{},"cmsObject.getUsers().each {\n",[48,8225,8226],{"class":50,"line":63},[48,8227,8228],{}," println it.name\n",[48,8230,8231],{"class":50,"line":69},[48,8232,266],{},[18,8234,8235],{},"How do you use it? You pass the path to the scripts that contain your logic to the shell script and it will execute them\nautomatically. Suppose the shell script is named groovyshell.sh and the groovy files are named createUsers.groovy and\nlistUsers.groovy. Execute them like this:",[18,8237,8238],{},[45,8239,8240],{},"./groovyshell.sh createUsers.groovy listUsers.groovy",[18,8242,8243],{},"You will see the familiar OpenCms startup sequence followed by the output of the second script:",[38,8245,8247],{"className":7707,"code":8246,"language":7709,"meta":43,"style":43},"\n...\nWelcome to the OpenCms shell!\nThis is OpenCms 7.5.x.\nCopyright (c) 2010 Alkacon Software GmbH\nOpenCms comes with ABSOLUTELY NO WARRANTY\nThis is free software, and you are welcome to\nredistribute it under certain conditions.\nPlease see the GNU Lesser General Public Licence for\nfurther details.\nhelp Shows this text.\nhelp * Shows the signatures of all available methods.\nhelp {string} Shows the signatures of all methods containing this string.\nexit or quit Leaves this OpenCms Shell.\nAdmin\nExport\nGuest\nUser0\nUser1\nUser2\nUser3\nUser4\nUser5\nUser6\nUser7\nUser8\nUser9\nGoodbye!\n...\n\n",[45,8248,8249,8253,8257,8274,8287,8295,8313,8340,8357,8385,8393,8407,8433,8462,8483,8488,8493,8498,8503,8508,8513,8518,8523,8528,8533,8538,8543,8548,8553],{"__ignoreMap":43},[48,8250,8251],{"class":50,"line":51},[48,8252,178],{"emptyLinePlaceholder":177},[48,8254,8255],{"class":50,"line":57},[48,8256,2202],{"class":471},[48,8258,8259,8262,8265,8268,8271],{"class":50,"line":63},[48,8260,8261],{"class":467},"Welcome",[48,8263,8264],{"class":475}," to",[48,8266,8267],{"class":475}," the",[48,8269,8270],{"class":475}," OpenCms",[48,8272,8273],{"class":475}," shell!\n",[48,8275,8276,8279,8282,8284],{"class":50,"line":69},[48,8277,8278],{"class":467},"This",[48,8280,8281],{"class":475}," is",[48,8283,8270],{"class":475},[48,8285,8286],{"class":475}," 7.5.x.\n",[48,8288,8289,8292],{"class":50,"line":75},[48,8290,8291],{"class":467},"Copyright",[48,8293,8294],{"class":482}," (c) 2010 Alkacon Software GmbH\n",[48,8296,8297,8299,8302,8304,8307,8310],{"class":50,"line":81},[48,8298,7393],{"class":467},[48,8300,8301],{"class":475}," comes",[48,8303,596],{"class":475},[48,8305,8306],{"class":475}," ABSOLUTELY",[48,8308,8309],{"class":475}," NO",[48,8311,8312],{"class":475}," WARRANTY\n",[48,8314,8315,8317,8319,8322,8325,8328,8331,8334,8337],{"class":50,"line":124},[48,8316,8278],{"class":467},[48,8318,8281],{"class":475},[48,8320,8321],{"class":475}," free",[48,8323,8324],{"class":475}," software,",[48,8326,8327],{"class":475}," and",[48,8329,8330],{"class":475}," you",[48,8332,8333],{"class":475}," are",[48,8335,8336],{"class":475}," welcome",[48,8338,8339],{"class":475}," to\n",[48,8341,8342,8345,8348,8351,8354],{"class":50,"line":129},[48,8343,8344],{"class":467},"redistribute",[48,8346,8347],{"class":475}," it",[48,8349,8350],{"class":475}," under",[48,8352,8353],{"class":475}," certain",[48,8355,8356],{"class":475}," conditions.\n",[48,8358,8359,8362,8365,8367,8370,8373,8376,8379,8382],{"class":50,"line":204},[48,8360,8361],{"class":467},"Please",[48,8363,8364],{"class":475}," see",[48,8366,8267],{"class":475},[48,8368,8369],{"class":475}," GNU",[48,8371,8372],{"class":475}," Lesser",[48,8374,8375],{"class":475}," General",[48,8377,8378],{"class":475}," Public",[48,8380,8381],{"class":475}," Licence",[48,8383,8384],{"class":475}," for\n",[48,8386,8387,8390],{"class":50,"line":210},[48,8388,8389],{"class":467},"further",[48,8391,8392],{"class":475}," details.\n",[48,8394,8395,8398,8401,8404],{"class":50,"line":216},[48,8396,8397],{"class":467},"help",[48,8399,8400],{"class":475}," Shows",[48,8402,8403],{"class":475}," this",[48,8405,8406],{"class":475}," text.\n",[48,8408,8409,8411,8413,8416,8418,8421,8424,8427,8430],{"class":50,"line":357},[48,8410,8397],{"class":467},[48,8412,472],{"class":471},[48,8414,8415],{"class":475}," Shows",[48,8417,8267],{"class":475},[48,8419,8420],{"class":475}," signatures",[48,8422,8423],{"class":475}," of",[48,8425,8426],{"class":475}," all",[48,8428,8429],{"class":475}," available",[48,8431,8432],{"class":475}," methods.\n",[48,8434,8435,8437,8440,8443,8445,8447,8449,8451,8454,8457,8459],{"class":50,"line":363},[48,8436,8397],{"class":467},[48,8438,8439],{"class":475}," {string}",[48,8441,8442],{"class":475}," Shows",[48,8444,8267],{"class":475},[48,8446,8420],{"class":475},[48,8448,8423],{"class":475},[48,8450,8426],{"class":475},[48,8452,8453],{"class":475}," methods",[48,8455,8456],{"class":475}," containing",[48,8458,8403],{"class":475},[48,8460,8461],{"class":475}," string.\n",[48,8463,8464,8467,8470,8473,8476,8478,8480],{"class":50,"line":369},[48,8465,8466],{"class":471},"exit",[48,8468,8469],{"class":475}," or",[48,8471,8472],{"class":475}," quit",[48,8474,8475],{"class":475}," Leaves",[48,8477,8403],{"class":475},[48,8479,8270],{"class":475},[48,8481,8482],{"class":475}," Shell.\n",[48,8484,8485],{"class":50,"line":3187},[48,8486,8487],{"class":467},"Admin\n",[48,8489,8490],{"class":50,"line":3193},[48,8491,8492],{"class":467},"Export\n",[48,8494,8495],{"class":50,"line":3199},[48,8496,8497],{"class":467},"Guest\n",[48,8499,8500],{"class":50,"line":3205},[48,8501,8502],{"class":467},"User0\n",[48,8504,8505],{"class":50,"line":3211},[48,8506,8507],{"class":467},"User1\n",[48,8509,8510],{"class":50,"line":3217},[48,8511,8512],{"class":467},"User2\n",[48,8514,8515],{"class":50,"line":3223},[48,8516,8517],{"class":467},"User3\n",[48,8519,8520],{"class":50,"line":3229},[48,8521,8522],{"class":467},"User4\n",[48,8524,8525],{"class":50,"line":3235},[48,8526,8527],{"class":467},"User5\n",[48,8529,8530],{"class":50,"line":3241},[48,8531,8532],{"class":467},"User6\n",[48,8534,8535],{"class":50,"line":3246},[48,8536,8537],{"class":467},"User7\n",[48,8539,8540],{"class":50,"line":3251},[48,8541,8542],{"class":467},"User8\n",[48,8544,8545],{"class":50,"line":3256},[48,8546,8547],{"class":467},"User9\n",[48,8549,8550],{"class":50,"line":3261},[48,8551,8552],{"class":467},"Goodbye!\n",[48,8554,8555],{"class":50,"line":3266},[48,8556,2202],{"class":471},[18,8558,8559],{},"I think this will be useful for us in the future, maybe also for you?",[394,8561,8562],{},"html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":43,"searchDepth":57,"depth":57,"links":8564},[],[403,404],"2011-01-10T15:16:36","OpenCms ships with a shell script for accessing the virtual file system from the command line.\\nThis is useful for a lot of administrative tasks like importing modules or exporting content. You can supply scripts\\nthat issue commands or use the shell interactively. As the syntax for the scripts is quite limited some tasks can’t be\\nachieved that easily. This blogpost\\ndescribes a way to circumvent these problems by generating the script files.","https://synyx.de/blog/scripting-opencms/",{},"/blog/scripting-opencms",{"title":7664,"description":8572},"OpenCms ships with a shell script for accessing the virtual file system from the command line.\nThis is useful for a lot of administrative tasks like importing modules or exporting content. You can supply scripts\nthat issue commands or use the shell interactively. As the syntax for the scripts is quite limited some tasks can’t be\nachieved that easily. This blogpost\ndescribes a way to circumvent these problems by generating the script files.","blog/scripting-opencms",[7691,5624],"OpenCms ships with a shell script for accessing the virtual file system from the command line. This is useful for a lot of administrative tasks like importing modules or exporting…","v8fncIfA9ZnYPM1Luj9Uvx7ZbqqqhEZaXHZoobwoM-0",{"id":8578,"title":8579,"author":8580,"body":8581,"category":8983,"date":8984,"description":8985,"extension":409,"link":8986,"meta":8987,"navigation":177,"path":8988,"seo":8989,"slug":8585,"stem":8991,"tags":8992,"teaser":8993,"__hash__":8994},"blog/blog/integration-tests-for-your-solr-config.md","Integration tests for your Solr config",[7061],{"type":11,"value":8582,"toc":8981},[8583,8586,8597,8606,8609,8737,8740,8743,8746,8979],[14,8584,8579],{"id":8585},"integration-tests-for-your-solr-config",[18,8587,8588,8591,8592,8596],{},[22,8589,7088],{"href":7086,"rel":8590},[26]," is a search server that bundles a lot of\nuseful ",[22,8593,8595],{"href":7092,"rel":8594},[26],"Lucene"," modules and provides an HTTP interface for querying and updating the data.\nThe index and most of the query mechanisms are configured using XML documents, client applications normally don’t need\nto be changed when adjusting the server configuration. As the server configuration heavily influences the quality of\nyour users search experience it’s a good idea to implement some integration tests that validate your functionality.",[18,8598,8599,8600,8605],{},"Solr ships with a useful abstract ",[22,8601,8604],{"href":8602,"rel":8603},"http://junit.org/",[26],"JUnit"," test case that can be used as a basis for your integration\ntests. I will demonstrate how to fire up a simple test using maven.",[18,8607,8608],{},"The most important part is the dependencies section of the pom:",[38,8610,8612],{"className":2193,"code":8611,"language":2195,"meta":43,"style":43},"\n \u003Cdependency>\n \u003CgroupId>junit\u003C/groupId>\n \u003CartifactId>junit\u003C/artifactId>\n \u003Cversion>4.7\u003C/version>\n \u003Ctype>jar\u003C/type>\n \u003Cscope>test\u003C/scope>\n \u003C/dependency>\n \u003C!-- dependencies needed for Solr integration test-->\n \u003Cdependency>\n \u003CgroupId>org.apache.solr\u003C/groupId>\n \u003CartifactId>solr-core\u003C/artifactId>\n \u003Cversion>1.4.1\u003C/version>\n \u003Cscope>test\u003C/scope>\n \u003C/dependency>\n \u003Cdependency>\n \u003CgroupId>org.slf4j\u003C/groupId>\n \u003CartifactId>slf4j-simple\u003C/artifactId>\n \u003Cversion>1.6.1\u003C/version>\n \u003Cscope>test\u003C/scope>\n \u003C/dependency>\n \u003Cdependency>\n \u003CgroupId>javax.servlet\u003C/groupId>\n \u003CartifactId>servlet-api\u003C/artifactId>\n \u003Cversion>2.5\u003C/version>\n \u003Cscope>test\u003C/scope>\n \u003C/dependency>\n\n",[45,8613,8614,8618,8622,8627,8632,8637,8642,8647,8651,8656,8660,8665,8670,8675,8679,8683,8687,8692,8697,8702,8706,8710,8714,8719,8724,8729,8733],{"__ignoreMap":43},[48,8615,8616],{"class":50,"line":51},[48,8617,178],{"emptyLinePlaceholder":177},[48,8619,8620],{"class":50,"line":57},[48,8621,2916],{},[48,8623,8624],{"class":50,"line":63},[48,8625,8626],{}," \u003CgroupId>junit\u003C/groupId>\n",[48,8628,8629],{"class":50,"line":69},[48,8630,8631],{}," \u003CartifactId>junit\u003C/artifactId>\n",[48,8633,8634],{"class":50,"line":75},[48,8635,8636],{}," \u003Cversion>4.7\u003C/version>\n",[48,8638,8639],{"class":50,"line":81},[48,8640,8641],{}," \u003Ctype>jar\u003C/type>\n",[48,8643,8644],{"class":50,"line":124},[48,8645,8646],{}," \u003Cscope>test\u003C/scope>\n",[48,8648,8649],{"class":50,"line":129},[48,8650,2936],{},[48,8652,8653],{"class":50,"line":204},[48,8654,8655],{}," \u003C!-- dependencies needed for Solr integration test-->\n",[48,8657,8658],{"class":50,"line":210},[48,8659,2916],{},[48,8661,8662],{"class":50,"line":216},[48,8663,8664],{}," \u003CgroupId>org.apache.solr\u003C/groupId>\n",[48,8666,8667],{"class":50,"line":357},[48,8668,8669],{}," \u003CartifactId>solr-core\u003C/artifactId>\n",[48,8671,8672],{"class":50,"line":363},[48,8673,8674],{}," \u003Cversion>1.4.1\u003C/version>\n",[48,8676,8677],{"class":50,"line":369},[48,8678,8646],{},[48,8680,8681],{"class":50,"line":3187},[48,8682,2936],{},[48,8684,8685],{"class":50,"line":3193},[48,8686,2916],{},[48,8688,8689],{"class":50,"line":3199},[48,8690,8691],{}," \u003CgroupId>org.slf4j\u003C/groupId>\n",[48,8693,8694],{"class":50,"line":3205},[48,8695,8696],{}," \u003CartifactId>slf4j-simple\u003C/artifactId>\n",[48,8698,8699],{"class":50,"line":3211},[48,8700,8701],{}," \u003Cversion>1.6.1\u003C/version>\n",[48,8703,8704],{"class":50,"line":3217},[48,8705,8646],{},[48,8707,8708],{"class":50,"line":3223},[48,8709,2936],{},[48,8711,8712],{"class":50,"line":3229},[48,8713,2916],{},[48,8715,8716],{"class":50,"line":3235},[48,8717,8718],{}," \u003CgroupId>javax.servlet\u003C/groupId>\n",[48,8720,8721],{"class":50,"line":3241},[48,8722,8723],{}," \u003CartifactId>servlet-api\u003C/artifactId>\n",[48,8725,8726],{"class":50,"line":3246},[48,8727,8728],{}," \u003Cversion>2.5\u003C/version>\n",[48,8730,8731],{"class":50,"line":3251},[48,8732,8646],{},[48,8734,8735],{"class":50,"line":3256},[48,8736,2936],{},[18,8738,8739],{},"We are including a recent JUnit version to enjoy some of the annotation goodness. solr-core contains all of the server\ncomponents as well as the test case, slf4j is used for logging. Of course you have to check if any of the artifacts\nconflict with runtime or compile time dependencies.",[18,8741,8742],{},"To run a simple test case against the example index config shipped with solr 1.4.1 copy or link the folder\napache-solr-1.4.1/example/solr/ to your projects basedir.",[18,8744,8745],{},"An example test case that checks if a value is found for a valid search:",[38,8747,8749],{"className":2193,"code":8748,"language":2195,"meta":43,"style":43},"\nimport java.io.IOException;\nimport org.apache.solr.client.solrj.embedded.EmbeddedSolrServer;\nimport org.apache.solr.util.AbstractSolrTestCase;\nimport org.apache.solr.client.solrj.SolrQuery;\nimport org.apache.solr.client.solrj.SolrServer;\nimport org.apache.solr.client.solrj.SolrServerException;\nimport org.apache.solr.client.solrj.response.QueryResponse;\nimport org.apache.solr.common.SolrInputDocument;\nimport org.apache.solr.common.params.SolrParams;\nimport org.junit.Before;\nimport org.junit.Test;\nimport static org.junit.Assert.assertEquals;\npublic class SolrSearchConfigTest extends AbstractSolrTestCase {\n private SolrServer server;\n @Override\n public String getSchemaFile() {\n return \"solr/conf/schema.xml\";\n }\n @Override\n public String getSolrConfigFile() {\n return \"solr/conf/solrconfig.xml\";\n }\n @Before\n @Override\n public void setUp() throws Exception {\n super.setUp();\n server = new EmbeddedSolrServer(h.getCoreContainer(), h.getCore().getName());\n }\n @Test\n public void testThatNoResultsAreReturned() throws SolrServerException {\n SolrParams params = new SolrQuery(\"text that is not found\");\n QueryResponse response = server.query(params);\n assertEquals(0L, response.getResults().getNumFound());\n }\n @Test\n public void testThatDocumentIsFound() throws SolrServerException, IOException {\n SolrInputDocument document = new SolrInputDocument();\n document.addField(\"id\", \"1\");\n document.addField(\"name\", \"my name\");\n server.add(document);\n server.commit();\n SolrParams params = new SolrQuery(\"name\");\n QueryResponse response = server.query(params);\n assertEquals(1L, response.getResults().getNumFound());\n assertEquals(\"1\", response.getResults().get(0).get(\"id\"));\n }\n}\n\n",[45,8750,8751,8755,8760,8765,8770,8775,8780,8785,8790,8795,8800,8805,8810,8815,8820,8825,8830,8835,8840,8844,8848,8853,8858,8862,8867,8871,8876,8881,8886,8890,8894,8899,8904,8909,8914,8918,8922,8927,8932,8937,8942,8947,8952,8957,8961,8966,8971,8975],{"__ignoreMap":43},[48,8752,8753],{"class":50,"line":51},[48,8754,178],{"emptyLinePlaceholder":177},[48,8756,8757],{"class":50,"line":57},[48,8758,8759],{},"import java.io.IOException;\n",[48,8761,8762],{"class":50,"line":63},[48,8763,8764],{},"import org.apache.solr.client.solrj.embedded.EmbeddedSolrServer;\n",[48,8766,8767],{"class":50,"line":69},[48,8768,8769],{},"import org.apache.solr.util.AbstractSolrTestCase;\n",[48,8771,8772],{"class":50,"line":75},[48,8773,8774],{},"import org.apache.solr.client.solrj.SolrQuery;\n",[48,8776,8777],{"class":50,"line":81},[48,8778,8779],{},"import org.apache.solr.client.solrj.SolrServer;\n",[48,8781,8782],{"class":50,"line":124},[48,8783,8784],{},"import org.apache.solr.client.solrj.SolrServerException;\n",[48,8786,8787],{"class":50,"line":129},[48,8788,8789],{},"import org.apache.solr.client.solrj.response.QueryResponse;\n",[48,8791,8792],{"class":50,"line":204},[48,8793,8794],{},"import org.apache.solr.common.SolrInputDocument;\n",[48,8796,8797],{"class":50,"line":210},[48,8798,8799],{},"import org.apache.solr.common.params.SolrParams;\n",[48,8801,8802],{"class":50,"line":216},[48,8803,8804],{},"import org.junit.Before;\n",[48,8806,8807],{"class":50,"line":357},[48,8808,8809],{},"import org.junit.Test;\n",[48,8811,8812],{"class":50,"line":363},[48,8813,8814],{},"import static org.junit.Assert.assertEquals;\n",[48,8816,8817],{"class":50,"line":369},[48,8818,8819],{},"public class SolrSearchConfigTest extends AbstractSolrTestCase {\n",[48,8821,8822],{"class":50,"line":3187},[48,8823,8824],{}," private SolrServer server;\n",[48,8826,8827],{"class":50,"line":3193},[48,8828,8829],{}," @Override\n",[48,8831,8832],{"class":50,"line":3199},[48,8833,8834],{}," public String getSchemaFile() {\n",[48,8836,8837],{"class":50,"line":3205},[48,8838,8839],{}," return \"solr/conf/schema.xml\";\n",[48,8841,8842],{"class":50,"line":3211},[48,8843,261],{},[48,8845,8846],{"class":50,"line":3217},[48,8847,8829],{},[48,8849,8850],{"class":50,"line":3223},[48,8851,8852],{}," public String getSolrConfigFile() {\n",[48,8854,8855],{"class":50,"line":3229},[48,8856,8857],{}," return \"solr/conf/solrconfig.xml\";\n",[48,8859,8860],{"class":50,"line":3235},[48,8861,261],{},[48,8863,8864],{"class":50,"line":3241},[48,8865,8866],{}," @Before\n",[48,8868,8869],{"class":50,"line":3246},[48,8870,8829],{},[48,8872,8873],{"class":50,"line":3251},[48,8874,8875],{}," public void setUp() throws Exception {\n",[48,8877,8878],{"class":50,"line":3256},[48,8879,8880],{}," super.setUp();\n",[48,8882,8883],{"class":50,"line":3261},[48,8884,8885],{}," server = new EmbeddedSolrServer(h.getCoreContainer(), h.getCore().getName());\n",[48,8887,8888],{"class":50,"line":3266},[48,8889,261],{},[48,8891,8892],{"class":50,"line":3271},[48,8893,331],{},[48,8895,8896],{"class":50,"line":3277},[48,8897,8898],{}," public void testThatNoResultsAreReturned() throws SolrServerException {\n",[48,8900,8901],{"class":50,"line":3283},[48,8902,8903],{}," SolrParams params = new SolrQuery(\"text that is not found\");\n",[48,8905,8906],{"class":50,"line":3289},[48,8907,8908],{}," QueryResponse response = server.query(params);\n",[48,8910,8911],{"class":50,"line":3295},[48,8912,8913],{}," assertEquals(0L, response.getResults().getNumFound());\n",[48,8915,8916],{"class":50,"line":3300},[48,8917,261],{},[48,8919,8920],{"class":50,"line":3305},[48,8921,331],{},[48,8923,8924],{"class":50,"line":3310},[48,8925,8926],{}," public void testThatDocumentIsFound() throws SolrServerException, IOException {\n",[48,8928,8929],{"class":50,"line":3315},[48,8930,8931],{}," SolrInputDocument document = new SolrInputDocument();\n",[48,8933,8934],{"class":50,"line":3320},[48,8935,8936],{}," document.addField(\"id\", \"1\");\n",[48,8938,8939],{"class":50,"line":3325},[48,8940,8941],{}," document.addField(\"name\", \"my name\");\n",[48,8943,8944],{"class":50,"line":3330},[48,8945,8946],{}," server.add(document);\n",[48,8948,8949],{"class":50,"line":3335},[48,8950,8951],{}," server.commit();\n",[48,8953,8954],{"class":50,"line":3340},[48,8955,8956],{}," SolrParams params = new SolrQuery(\"name\");\n",[48,8958,8959],{"class":50,"line":3900},[48,8960,8908],{},[48,8962,8963],{"class":50,"line":3906},[48,8964,8965],{}," assertEquals(1L, response.getResults().getNumFound());\n",[48,8967,8968],{"class":50,"line":3912},[48,8969,8970],{}," assertEquals(\"1\", response.getResults().get(0).get(\"id\"));\n",[48,8972,8973],{"class":50,"line":3918},[48,8974,261],{},[48,8976,8977],{"class":50,"line":3924},[48,8978,266],{},[394,8980,396],{},{"title":43,"searchDepth":57,"depth":57,"links":8982},[],[403,404],"2011-01-01T19:31:22","Solr is a search server that bundles a lot of\\nuseful Lucene modules and provides an HTTP interface for querying and updating the data.\\nThe index and most of the query mechanisms are configured using XML documents, client applications normally don’t need\\nto be changed when adjusting the server configuration. As the server configuration heavily influences the quality of\\nyour users search experience it’s a good idea to implement some integration tests that validate your functionality.","https://synyx.de/blog/integration-tests-for-your-solr-config/",{},"/blog/integration-tests-for-your-solr-config",{"title":8579,"description":8990},"Solr is a search server that bundles a lot of\nuseful Lucene modules and provides an HTTP interface for querying and updating the data.\nThe index and most of the query mechanisms are configured using XML documents, client applications normally don’t need\nto be changed when adjusting the server configuration. As the server configuration heavily influences the quality of\nyour users search experience it’s a good idea to implement some integration tests that validate your functionality.","blog/integration-tests-for-your-solr-config",[7053,5626,6300],"Solr is a search server that bundles a lot of useful Lucene modules and provides an HTTP interface for querying and updating the data. The index and most of the…","tIqboctYIr9FB0W_MW0lZsbkuMIgue2OGo8FnULd54M",{"id":8996,"title":8997,"author":8998,"body":8999,"category":9037,"date":9038,"description":9039,"extension":409,"link":9040,"meta":9041,"navigation":177,"path":9042,"seo":9043,"slug":9003,"stem":9045,"tags":9046,"teaser":9048,"__hash__":9049},"blog/blog/netbeans-and-opencms.md","Netbeans and OpenCms",[7061],{"type":11,"value":9000,"toc":9035},[9001,9004,9011,9024,9027,9032],[14,9002,8997],{"id":9003},"netbeans-and-opencms",[18,9005,9006,9010],{},[22,9007,7393],{"href":9008,"rel":9009},"http://opencms.org",[26]," stores all its content like JSP-templates, images and CSS files in a virtual file system\nwhich makes it impossible to use normal development models. As we are using it for several years now we’ve always been\ntrying to improve our development processes.",[18,9012,9013,9014,9019,9020,392],{},"One of the results is a custom ",[22,9015,9018],{"href":9016,"rel":9017},"http://netbeans.org",[26],"Netbeans"," plugin for working with OpenCms. We’ve been using it\nsuccessfully in several projects but didn’t find the time to release it to the public until today. The plugin can now be\ndownloaded on our ",[22,9021,9023],{"href":7397,"rel":9022},[26],"open source project site",[18,9025,9026],{},"It consists of a combination of a Netbeans plugin and an OpenCms module and is targeted at development environments.\nFiles can be uploaded using the Netbeans context menu. This drastically improves the development time as changes can be\napplied and checked immediately.",[18,9028,9029],{},[1195,9030],{"alt":43,"src":9031},"https://media.synyx.de/uploads//2010/11/netbeans-dialogsmall.png",[18,9033,9034],{},"Of course we are interested if this plugin is useful for anybody so leave a comment if you like it. If you are\ninterested in any enhancements or you found a bug just issue a ticket in redmine.",{"title":43,"searchDepth":57,"depth":57,"links":9036},[],[403,404],"2010-11-26T18:31:57","OpenCms stores all its content like JSP-templates, images and CSS files in a virtual file system\\nwhich makes it impossible to use normal development models. As we are using it for several years now we’ve always been\\ntrying to improve our development processes.","https://synyx.de/blog/netbeans-and-opencms/",{},"/blog/netbeans-and-opencms",{"title":8997,"description":9044},"OpenCms stores all its content like JSP-templates, images and CSS files in a virtual file system\nwhich makes it impossible to use normal development models. As we are using it for several years now we’ve always been\ntrying to improve our development processes.","blog/netbeans-and-opencms",[9047,5624],"netbeans","OpenCms stores all its content like JSP-templates, images and CSS files in a virtual file system which makes it impossible to use normal development models. As we are using it…","Q9FAJClXp5mBFEXH6TKZXjpr0KEBVv4APPwpv1WY2_8",{"id":9051,"title":9052,"author":9053,"body":9054,"category":9098,"date":9099,"description":9100,"extension":409,"link":9101,"meta":9102,"navigation":177,"path":9103,"seo":9104,"slug":9058,"stem":9106,"tags":9107,"teaser":9110,"__hash__":9111},"blog/blog/logging-to-multiple-files-using-log4j.md","Logging to multiple files using log4j",[7061],{"type":11,"value":9055,"toc":9096},[9056,9059,9068,9071,9074,9077,9080,9083,9086,9093],[14,9057,9052],{"id":9058},"logging-to-multiple-files-using-log4j",[18,9060,9061,9062,9067],{},"Sometimes even the simple things take quite some time. For a special application log I’ve been searching for a way to\nwrite log calls for one package to a separate file using Log4j. I’ve been searching the web, skimming through the log4j\ndocumentation but didn’t really find anything. ",[22,9063,9066],{"href":9064,"rel":9065},"http://www.junlu.com/msg/93394.html",[26],"This message",", though only a\nquestion, contained the missing hint.",[18,9069,9070],{},"Suppose you have a log configuration that already has root loggers configured. To make only one package log to another\nfile, but not to the root logger appenders, you add something like this:",[18,9072,9073],{},"`log4j.logger.my.Logger=INFO,FILE",[18,9075,9076],{},"log4j.additivity.my.Logger=false",[18,9078,9079],{},"log4j.appender.FILE=org.apache.log4j.RollingFileAppender",[18,9081,9082],{},"log4j.appender.FILE.File=include-performance.log",[18,9084,9085],{},"log4j.appender.FILE.layout=org.apache.log4j.PatternLayout",[18,9087,9088,9089,9092],{},"log4j.appender.FILE.layout.ConversionPattern=%d{DATE} %5p ",[48,9090,9091],{},"%30.30C:%4L"," %m%n`",[18,9094,9095],{},"What does it do? In the first line you create a logger that logs anything above info inclusive. In the same line,\nseparated by a comma, you add the name of your appender. By setting additivity to false you prevent the logger to\ninherit any loggers from ancestors (including any root loggers).",{"title":43,"searchDepth":57,"depth":57,"links":9097},[],[403,404],"2010-11-24T18:46:17","Sometimes even the simple things take quite some time. For a special application log I’ve been searching for a way to\\nwrite log calls for one package to a separate file using Log4j. I’ve been searching the web, skimming through the log4j\\ndocumentation but didn’t really find anything. This message, though only a\\nquestion, contained the missing hint.","https://synyx.de/blog/logging-to-multiple-files-using-log4j/",{},"/blog/logging-to-multiple-files-using-log4j",{"title":9052,"description":9105},"Sometimes even the simple things take quite some time. For a special application log I’ve been searching for a way to\nwrite log calls for one package to a separate file using Log4j. I’ve been searching the web, skimming through the log4j\ndocumentation but didn’t really find anything. This message, though only a\nquestion, contained the missing hint.","blog/logging-to-multiple-files-using-log4j",[9108,9109],"log4j","logging","Sometimes even the simple things take quite some time. For a special application log I’ve been searching for a way to write log calls for one package to a separate…","sdX013OPkMBq0Tfuuz2mTT8DTbfSaM4rGRwxRY32Qzw",{"id":9113,"title":9114,"author":9115,"body":9116,"category":9280,"date":9281,"description":9282,"extension":409,"link":9283,"meta":9284,"navigation":177,"path":9285,"seo":9286,"slug":9120,"stem":9288,"tags":9289,"teaser":9290,"__hash__":9291},"blog/blog/using-cmsshell-on-ubuntu-systems.md","Using CmsShell on Ubuntu systems",[7061],{"type":11,"value":9117,"toc":9278},[9118,9121,9130,9133,9139,9146,9160,9163,9168,9171,9176,9182,9256,9259,9265,9268,9273,9276],[14,9119,9114],{"id":9120},"using-cmsshell-on-ubuntu-systems",[18,9122,9123,9124,9127,9128,392],{},"CmsShell is a neat tool to access the ",[22,9125,7393],{"href":9008,"rel":9126},[26]," VFS from the command line. This can be extremely\nuseful when your system can’t be accessed anymore using the web interface or when performing batch updates. The script\ncan be found in the OpenCms webapp at ",[45,9129,7698],{},[18,9131,9132],{},"Unfortunately the script that ships with the OpenCms webapp doesn’t work on Ubuntu systems as it is. These are the steps\nto make it run.",[18,9134,9135,9136],{},"First be sure that it’s executable: ",[45,9137,9138],{},"chmod +x cmsshell.sh",[18,9140,9141,9142,9145],{},"When trying to run it using ",[45,9143,9144],{},"./cmsshell.sh"," you will very likely see an error:",[38,9147,9149],{"className":2193,"code":9148,"language":2195,"meta":43,"style":43},"\nbash: ./cmsshell.sh: /bin/sh^M: bad interpreter: No such file or directory\n\n",[45,9150,9151,9155],{"__ignoreMap":43},[48,9152,9153],{"class":50,"line":51},[48,9154,178],{"emptyLinePlaceholder":177},[48,9156,9157],{"class":50,"line":57},[48,9158,9159],{},"bash: ./cmsshell.sh: /bin/sh^M: bad interpreter: No such file or directory\n",[18,9161,9162],{},"This is caused by dos line breaks that are included in the file. A tool to remove those can be found in the package\ntofrodos (used to be in sysutils):",[18,9164,9165],{},[45,9166,9167],{},"sudo apt-get install tofrodos",[18,9169,9170],{},"Run it on the file by issuing",[18,9172,9173],{},[45,9174,9175],{},"dos2unix cmsshell.sh",[18,9177,9178,9179,9181],{},"Try to run the file again: ",[45,9180,9144],{},", which will result in another error:",[38,9183,9185],{"className":2193,"code":9184,"language":2195,"meta":43,"style":43},"\n/cmsshell.sh: 8: pushd: not found\n./cmsshell.sh: 9: dirs: not found\n./cmsshell.sh: 10: popd: not found\nException in thread \"main\" java.lang.NoClassDefFoundError: org/opencms/main/CmsShell\nCaused by: java.lang.ClassNotFoundException: org.opencms.main.CmsShell\n at java.net.URLClassLoader$1.run(URLClassLoader.java:200)\n at java.security.AccessController.doPrivileged(Native Method)\n at java.net.URLClassLoader.findClass(URLClassLoader.java:188)\n at java.lang.ClassLoader.loadClass(ClassLoader.java:307)\n at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)\n at java.lang.ClassLoader.loadClass(ClassLoader.java:252)\n at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:320)\nCould not find the main class: org.opencms.main.CmsShell. Program will exit.\n\n",[45,9186,9187,9191,9196,9201,9206,9211,9216,9221,9226,9231,9236,9241,9246,9251],{"__ignoreMap":43},[48,9188,9189],{"class":50,"line":51},[48,9190,178],{"emptyLinePlaceholder":177},[48,9192,9193],{"class":50,"line":57},[48,9194,9195],{},"/cmsshell.sh: 8: pushd: not found\n",[48,9197,9198],{"class":50,"line":63},[48,9199,9200],{},"./cmsshell.sh: 9: dirs: not found\n",[48,9202,9203],{"class":50,"line":69},[48,9204,9205],{},"./cmsshell.sh: 10: popd: not found\n",[48,9207,9208],{"class":50,"line":75},[48,9209,9210],{},"Exception in thread \"main\" java.lang.NoClassDefFoundError: org/opencms/main/CmsShell\n",[48,9212,9213],{"class":50,"line":81},[48,9214,9215],{},"Caused by: java.lang.ClassNotFoundException: org.opencms.main.CmsShell\n",[48,9217,9218],{"class":50,"line":124},[48,9219,9220],{}," at java.net.URLClassLoader$1.run(URLClassLoader.java:200)\n",[48,9222,9223],{"class":50,"line":129},[48,9224,9225],{}," at java.security.AccessController.doPrivileged(Native Method)\n",[48,9227,9228],{"class":50,"line":204},[48,9229,9230],{}," at java.net.URLClassLoader.findClass(URLClassLoader.java:188)\n",[48,9232,9233],{"class":50,"line":210},[48,9234,9235],{}," at java.lang.ClassLoader.loadClass(ClassLoader.java:307)\n",[48,9237,9238],{"class":50,"line":216},[48,9239,9240],{}," at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)\n",[48,9242,9243],{"class":50,"line":357},[48,9244,9245],{}," at java.lang.ClassLoader.loadClass(ClassLoader.java:252)\n",[48,9247,9248],{"class":50,"line":363},[48,9249,9250],{}," at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:320)\n",[48,9252,9253],{"class":50,"line":369},[48,9254,9255],{},"Could not find the main class: org.opencms.main.CmsShell. Program will exit.\n",[18,9257,9258],{},"To make it work you need to open the script and change the line",[18,9260,9261,9264],{},[45,9262,9263],{},"OPENCMS_BASE=","dirs +0``",[18,9266,9267],{},"to",[18,9269,9270,9272],{},[45,9271,9263],{},"pwd``",[18,9274,9275],{},"When saving the change and executing the script you should see OpenCms start and end at the prompt where you can login\nand execute any useful action you can think of.",[394,9277,396],{},{"title":43,"searchDepth":57,"depth":57,"links":9279},[],[2375,404],"2010-11-03T17:13:14","CmsShell is a neat tool to access the OpenCms VFS from the command line. This can be extremely\\nuseful when your system can’t be accessed anymore using the web interface or when performing batch updates. The script\\ncan be found in the OpenCms webapp at WEB-INF/cmsshell.sh.","https://synyx.de/blog/using-cmsshell-on-ubuntu-systems/",{},"/blog/using-cmsshell-on-ubuntu-systems",{"title":9114,"description":9287},"CmsShell is a neat tool to access the OpenCms VFS from the command line. This can be extremely\nuseful when your system can’t be accessed anymore using the web interface or when performing batch updates. The script\ncan be found in the OpenCms webapp at WEB-INF/cmsshell.sh.","blog/using-cmsshell-on-ubuntu-systems",[5711,5624],"CmsShell is a neat tool to access the OpenCms VFS from the command line. This can be extremely useful when your system can’t be accessed anymore using the web interface…","D3PyhEOAgZTPGgEbOBhZLYK4-r5C8IWO88rDvPj_q-k",{"id":9293,"title":9294,"author":9295,"body":9296,"category":9334,"date":9335,"description":9336,"extension":409,"link":9337,"meta":9338,"navigation":177,"path":9339,"seo":9340,"slug":9300,"stem":9341,"tags":9342,"teaser":9343,"__hash__":9344},"blog/blog/context-reload-with-tomcat.md","Context reload with Tomcat",[7061],{"type":11,"value":9297,"toc":9332},[9298,9301,9310,9313,9318,9321,9324],[14,9299,9294],{"id":9300},"context-reload-with-tomcat",[18,9302,9303,9304,9309],{},"Ever wondered why ",[22,9305,9308],{"href":9306,"rel":9307},"http://tomcat.apache.org/",[26],"Tomcat"," reloads the context when editing web.xml?",[18,9311,9312],{},"This is a default configuration that can also be adjusted to your needs. The file conf/context.xml is the default\ncontext configuration that is used for all webapps. In this file you can find the line",[18,9314,9315],{},[45,9316,9317],{},"\u003CWatchedResource>WEB-INF/web.xml\u003C/WatchedResource>",[18,9319,9320],{},"which triggers the reload for any web.xml.",[18,9322,9323],{},"You can either add more resources here or, preferably, add your own context configuration with your resources.",[18,9325,9326,9327,392],{},"Find out more about context configuration in\nthe ",[22,9328,9331],{"href":9329,"rel":9330},"http://tomcat.apache.org/tomcat-6.0-doc/config/context.html",[26],"Tomcat documentation",{"title":43,"searchDepth":57,"depth":57,"links":9333},[],[403,404],"2010-10-13T16:08:56","Ever wondered why Tomcat reloads the context when editing web.xml?","https://synyx.de/blog/context-reload-with-tomcat/",{},"/blog/context-reload-with-tomcat",{"title":9294,"description":9336},"blog/context-reload-with-tomcat",[3376],"Ever wondered why Tomcat reloads the context when editing web.xml? This is a default configuration that can also be adjusted to your needs. The file conf/context.xml is the default context…","rqgNbT2dAL4FFc59uZqZxj2Vd1hSH_5x_lWFp8y9NCs",{"id":9346,"title":9347,"author":9348,"body":9349,"category":9424,"date":9425,"description":9426,"extension":409,"link":9427,"meta":9428,"navigation":177,"path":9429,"seo":9430,"slug":9353,"stem":9431,"tags":9432,"teaser":9433,"__hash__":9434},"blog/blog/console-logging-with-opencms.md","Console logging with OpenCms",[7061],{"type":11,"value":9350,"toc":9422},[9351,9354,9359,9362,9388,9390,9417,9420],[14,9352,9347],{"id":9353},"console-logging-with-opencms",[18,9355,9356],{},[275,9357,9358],{},"We are currently in the process of cleaning up our internal wiki. A lot of information is quite outdated but it also\ncontains some useful snippets that we would like to share with the rest of the world.",[18,9360,9361],{},"The log4j ConsoleAppender is already configured in OpenCms log4j.properties but not enabled by default. To enable it\nchange the configuration",[38,9363,9367],{"className":9364,"code":9365,"language":9366,"meta":43,"style":43},"language-plain shiki shiki-themes github-light github-dark","\nlog4j.rootLogger=\\\n ERROR,\\\n OC\n\n","plain",[45,9368,9369,9373,9378,9383],{"__ignoreMap":43},[48,9370,9371],{"class":50,"line":51},[48,9372,178],{"emptyLinePlaceholder":177},[48,9374,9375],{"class":50,"line":57},[48,9376,9377],{},"log4j.rootLogger=\\\n",[48,9379,9380],{"class":50,"line":63},[48,9381,9382],{}," ERROR,\\\n",[48,9384,9385],{"class":50,"line":69},[48,9386,9387],{}," OC\n",[18,9389,9267],{},[38,9391,9393],{"className":9364,"code":9392,"language":9366,"meta":43,"style":43},"\nlog4j.rootLogger=\\\n ERROR,\\\n OC,\\\n CONSOLE\n\n",[45,9394,9395,9399,9403,9407,9412],{"__ignoreMap":43},[48,9396,9397],{"class":50,"line":51},[48,9398,178],{"emptyLinePlaceholder":177},[48,9400,9401],{"class":50,"line":57},[48,9402,9377],{},[48,9404,9405],{"class":50,"line":63},[48,9406,9382],{},[48,9408,9409],{"class":50,"line":69},[48,9410,9411],{}," OC,\\\n",[48,9413,9414],{"class":50,"line":75},[48,9415,9416],{}," CONSOLE\n",[18,9418,9419],{},"This is useful when starting OpenCms from within an IDE like Netbeans or Eclipse which display the Console window by\ndefault.",[394,9421,396],{},{"title":43,"searchDepth":57,"depth":57,"links":9423},[],[403,404],"2010-10-12T18:44:46","We are currently in the process of cleaning up our internal wiki. A lot of information is quite outdated but it also\\ncontains some useful snippets that we would like to share with the rest of the world.","https://synyx.de/blog/console-logging-with-opencms/",{},"/blog/console-logging-with-opencms",{"title":9347,"description":9358},"blog/console-logging-with-opencms",[5624],"We are currently in the process of cleaning up our internal wiki. A lot of information is quite outdated but it also contains some useful snippets that we would like…","YLxxqXYBKnGrglUy2I9bdVGutI6JPiBeaHv7xk9P0FM",{"id":9436,"title":9437,"author":9438,"body":9439,"category":9545,"date":9546,"description":9547,"extension":409,"link":9548,"meta":9549,"navigation":177,"path":9550,"seo":9551,"slug":9443,"stem":9553,"tags":9554,"teaser":9558,"__hash__":9559},"blog/blog/froscon-2010.md","FrOSCon 2010",[7061],{"type":11,"value":9440,"toc":9543},[9441,9444,9453,9456,9471,9492,9501,9516,9531,9534],[14,9442,9437],{"id":9443},"froscon-2010",[18,9445,9446,9447,9452],{},"Am 21. und 22.08. fand für mich die 2. ",[22,9448,9451],{"href":9449,"rel":9450},"http://froscon.de/",[26],"Free and Open Source Software Conference FrOSCon"," in St.\nAugustin bei Bonn statt. Der Hauptgrund für meinen Besuch im letzten Jahr war ein ausgedehnter Java-Track, ich war\njedoch von der Atmosphäre und der Vielfalt der Themen so begeistert, dass die Konferenz für mich sicher ein regelmäßiges\nEreignis sein wird.",[18,9454,9455],{},"Die Gelegenheit soll natürlich genutzt werden, um ein paar interessante Vorträge aus diesem Jahr vorzustellen, um dem\nein oder anderen vielleicht auch Lust auf einen Besuch zu machen.",[18,9457,9458,9459,9464,9465,9470],{},"Ein recht verbreitetes Thema, das unter anderem gerne im leider\neingestellten ",[22,9460,9463],{"href":9461,"rel":9462},"http://blog.stackoverflow.com/category/podcasts/",[26],"Stackoverflow-Podcast"," oder auch in diversen Büchern\nangesprochen wird, ist der Nutzen für die eigene Karriere, den man sich durch ein offenes Arbeiten in einer Community\nerarbeiten kann. ",[22,9466,9469],{"href":9467,"rel":9468},"http://www.lornajane.net/",[26],"Lorna Jane Mitchell"," beschrieb in “Open Source Your Career” recht\nunterhaltsam von Ihren Anfängen in der PHP-Community und den ersten Auftritten auf Konferenzen. Eine Anreiz für mehr\nEngagement.",[18,9472,9473,9474,9479,9480,9485,9486,9491],{},"Obwohl ich mit den Grundlagen schon vertraut war, waren zwei Vorträge zu ",[22,9475,9478],{"href":9476,"rel":9477},"http://www.mongodb.org/",[26],"MongoDB"," interessant:\nEiner über MongoDB im generellen von einem Mitarbeiter von ",[22,9481,9484],{"href":9482,"rel":9483},"http://www.10gen.com/",[26],"10gen",", der Firma hinter der\nDatenbank, und einen zur Integration in Ruby on Rails von ",[22,9487,9490],{"href":9488,"rel":9489},"http://jan.krutisch.de/",[26],"Jan Krutisch",". Auch wenn die\nhorizontale Skalierung für mich momentan noch keine große Rolle spielen wird, kann ich mir vorstellen, dass der\ndokumentenorientierte Ansatz auch beim Einsatz auf einer Maschine Vorteile bringen kann. Ich plane das an einem\nkonkreten Problem einmal auszuprobieren, einfach nur um zu wissen, wie sich die Entwicklung anfühlt.",[18,9493,9494,9495,9500],{},"“Mobile Linux Development” von Christian Küster ging mit einem für mich neuen Blickwinkel auf\nein ",[22,9496,9499],{"href":9497,"rel":9498},"http://mobile.synyx.de",[26],"bekanntes Thema"," zu: Wie unterscheiden sich die unterschiedlichen Linux-basierten mobilen\nBetriebssysteme in Bezug auf die Zugriffsmöglichkeiten auf die Kernkomponenten, welche erlauben beispielsweise ein\nAustauschen des Kernels oder den Zugriff auf Systemkomponenten. Android schnitt bei diesen Aspekten relativ schlecht ab,\nMaemo scheint die meisten Freiheitsgrade zu bieten. Für die Entwicklung auf den Geräten spielt die dies meiner Meinung\njedoch eine recht geringe Rolle, solange höherwertige Funktionen angeboten werden, mit denen die benötigten\nFunktionalitäten abgedeckt werden können.",[18,9502,9503,9504,9509,9510,9515],{},"Der Vortrag, wegen dem ich mich eigentlich zum Besuch der FrOSCon entschlossen hatte, Ruby on Rails 3\nvon ",[22,9505,9508],{"href":9506,"rel":9507},"http://yehudakatz.com/",[26],"Yehuda Katz",", war leider nicht so technisch, wie ich ihn mir gewünscht hatte. Gerade da er\nvon einem Mann aus dem ",[22,9511,9514],{"href":9512,"rel":9513},"http://rubyonrails.org/merb",[26],"Merb-Team"," gehalten wurde, hätte ich mir einen Überblick über die\nUnterschiede zwischen den Versionen gewünscht. Merb war ehemals ein Konkurrenz-Framework und geht mit Version 3 in Ruby\non Rails auf. Auch wenn mir die technischen Konzepte gefehlt haben war der Einblick in die Arbeit des Rails-Teams dann\ndoch interessant.",[18,9517,9518,9519,9524,9525,9530],{},"Kurzfristig eingeschoben wurde ein Talk von ",[22,9520,9523],{"href":9521,"rel":9522},"http://kippdata.de/",[26],"Rainer Jung"," zu den Neuerungen\nin ",[22,9526,9529],{"href":9527,"rel":9528},"http://httpd.apache.org/",[26],"Apache httpd"," 2.4. Besonders die Anforderungen an einen Webserver, die sich durch die\nstark steigende Anzahl an Connections durch die Verbreitung von AJAX-Anwendungen und das Offenhalten der Connections\ndurch Techniken wie WebSockets/Comet ergeben, waren spannend. Beeindruckend, dass Rainer Jung es nicht nur schafft, in\nzwei so wichtigen Projekten wie dem in C geschriebenen httpd und dem in Java geschriebenen Servlet-Container Tomcat\nCore-Committer zu sein, sondern auch beide Projekte gleichwertig vertreten kann, indem er Samstags ein Tomcat-Shirt\nund Sonntags ein Apache-Shirt trägt :).",[18,9532,9533],{},"Alles in allem war die FrOSCon auch in diesem Jahr wieder außerordentlich lohnend. Die lockere Atmosphäre ist mit keiner\nanderen Konferenz, die ich kenne, zu vergleichen, was sicher einerseits an dem Termin am Wochenende liegt und\nandererseits daran, dass die Konferenz weniger businesslastig ist, als die mir bekannten Java-Konferenzen. Trotzdem\nkann man jede Menge neuen Input für die tägliche Arbeit bekommen, ein Besuch lohnt sich also nicht nur wegen des extrem\nniedrigen Eintrittspreises von 5€.",[18,9535,9536,9537,9542],{},"Und noch ein praktischer Tipp am Rande: Wer kein Problem mit einem kleinen Fußmarsch hat, ist beim sehr freundlichen\nWirt im ",[22,9538,9541],{"href":9539,"rel":9540},"http://www.zum-laternchen.de/",[26],"Laternchen"," bestens aufgehoben.",{"title":43,"searchDepth":57,"depth":57,"links":9544},[],[404],"2010-08-24T06:16:08","Am 21. und 22.08. fand für mich die 2. Free and Open Source Software Conference FrOSCon in St.\\nAugustin bei Bonn statt. Der Hauptgrund für meinen Besuch im letzten Jahr war ein ausgedehnter Java-Track, ich war\\njedoch von der Atmosphäre und der Vielfalt der Themen so begeistert, dass die Konferenz für mich sicher ein regelmäßiges\\nEreignis sein wird.","https://synyx.de/blog/froscon-2010/",{},"/blog/froscon-2010",{"title":9437,"description":9552},"Am 21. und 22.08. fand für mich die 2. Free and Open Source Software Conference FrOSCon in St.\nAugustin bei Bonn statt. Der Hauptgrund für meinen Besuch im letzten Jahr war ein ausgedehnter Java-Track, ich war\njedoch von der Atmosphäre und der Vielfalt der Themen so begeistert, dass die Konferenz für mich sicher ein regelmäßiges\nEreignis sein wird.","blog/froscon-2010",[7052,5709,5710,9555,9556,5712,9557],"mobile","mongodb","ruby-on-rails","Am 21. und 22.08. fand für mich die 2. Free and Open Source Software Conference FrOSCon in St. Augustin bei Bonn statt. Der Hauptgrund für meinen Besuch im letzten Jahr…","I5FF7sxuFa3dbVLJ3H-3GJIR6OfzFdL06uiY3HOqsj4",{"id":9561,"title":9562,"author":9563,"body":9564,"category":9712,"date":9713,"description":9714,"extension":409,"link":9715,"meta":9716,"navigation":177,"path":9717,"seo":9718,"slug":9568,"stem":9719,"tags":9720,"teaser":9723,"__hash__":9724},"blog/blog/template-based-document-generation-using-odfdom.md","Template based document generation using ODFDOM",[7061],{"type":11,"value":9565,"toc":9706},[9566,9569,9572,9587,9591,9600,9611,9614,9618,9626,9629,9632,9635,9638,9641,9645,9648,9655,9660,9663,9666,9669,9672,9675,9678,9681,9684,9687,9690,9693,9695,9698,9701,9703],[14,9567,9562],{"id":9568},"template-based-document-generation-using-odfdom",[18,9570,9571],{},"Generating documents from data that is managed by a web application is a quite common need. Think about letters that are\ngenerated for a customer relationship management system or bills that are to be send for membership fees. For corporate\nidentity reasons you don’t want these documents to look like generated from a plain text file but you want to have\nlogos, tables, address labels and so on.",[18,9573,9574,9575,9580,9581,9586],{},"As the people that are designing the look of these documents often are not programmers it is a good idea to provide a\nway to use well know tools for creating and editing templates for these documents. What we have been doing for some time\nis to let the customer create template documents using ",[22,9576,9579],{"href":9577,"rel":9578},"http://www.openoffice.org/",[26],"OpenOffice.org",", the open source\nword processor, and transform these documents programmatically. OpenOffice.org uses the\nstandardized ",[22,9582,9585],{"href":9583,"rel":9584},"http://www.oasis-open.org/committees/tc_home.php?wg_abbrev=office",[26],"Open Document"," format to save its\ndocuments. Open Document files are zip archives that contain some XML documents as well as additional content (images,\nmacros, …).",[30,9588,9590],{"id":9589},"the-uno-approach","The UNO approach",[18,9592,9593,9594,9599],{},"One of the older approaches we have been using for document processing is to access an OpenOffice.org instance running\non the server using the ",[22,9595,9598],{"href":9596,"rel":9597},"http://wiki.services.openoffice.org/wiki/Uno",[26],"UNO API",". UNO is a language agnostic API that\nprovides access to a lot of functionality of OpenOffice.org using an IDL. Though really powerful this approach also\nyields some drawbacks:",[868,9601,9602,9605,9608],{},[871,9603,9604],{},"Understanding and learning the UNO API is hard and takes a lot of time",[871,9606,9607],{},"Some features of a document can’t be accessed using the API (e.g. the id of form control elements is saved in the\ndocument but is not accessible using UNO)",[871,9609,9610],{},"An instance of OpenOffice.org can only be used by one thread at a time so you need some kind of instance pooling.",[18,9612,9613],{},"These drawbacks make it really hard to design and implement a robust system that can handle the load of a typical web\napplication and can still be maintained by a lot of developers.",[30,9615,9617],{"id":9616},"odfdom","ODFDOM",[18,9619,9620,9621,9625],{},"Some time after the standardization of the Open Document format a new project was\nborn: ",[22,9622,9617],{"href":9623,"rel":9624},"http://odftoolkit.org/projects/odfdom/pages/Home",[26],", a sub project of the odftoolkt project. ODFDOM is a\npure Java API that provides both low level DOM access to the Open Document XML format as well as convenience\nfunctionality to manipulate document data.",[18,9627,9628],{},"As with ODFDOM the application and the document generation all run on the Java Virtual Machine it is easier to maintain\nfrom an adminitrators perspective. Also in contrast to the UNO API ODFDOM is really easy to use.",[18,9630,9631],{},"The following snippet creates a new text document, inserts some text and saves the document to a temp file.",[18,9633,9634],{},"`OdfTextDocument doc = OdfTextDocument.newTextDocument();",[18,9636,9637],{},"doc.addText(\"Hello World!\");",[18,9639,9640],{},"doc.save(File.createTempFile(\"odfdom\", \".odt\"));`",[30,9642,9644],{"id":9643},"templating","Templating",[18,9646,9647],{},"To use Odfdom for templating you can choose one of the many placeholder approaches in OpenOffice.org. A very simple one\nis the use of user fields. To insert a user field in OpenOffice.org create a new document and go to Insert => Field\ncommand => Others. There you choose the tab variables and user field. You can add a name and a value. The value in our\ncase is only there to have a visual feedback when designing the document. The user field will be replaced automatically.",[18,9649,9650,9651,9654],{},"Let’s see how we can replace our placeholder value. The values for user fields as inserted above are stored in a node\n",[22,9652,9653],{"href":9653},"text:user-field-decl",". This is an excerpt from the Open Document content.xml for a simple example document:",[18,9656,9657],{},[45,9658,9659],{},"\u003Ctext:user-field-decl office:value-type=\"string\" office:string-value=\"hello\" text:name=\"test\"/>",[18,9661,9662],{},"The user field is named test, it’s initial value for visual feedback is set to “hello”.",[18,9664,9665],{},"Imagine that the data that we want to replace with the values in the template is stored in a simple Map of Strings. To\nreplace all dummy values with values from you application you can access the nodes using the method\ngetElementsByTagName(“element”):",[18,9667,9668],{},"`Map\u003CString, String> values = new HashMap\u003CString, String>();",[18,9670,9671],{},"values.put(\"test\", \"inserted automatically\");",[18,9673,9674],{},"OdfDocument doc = OdfDocument.loadDocument(\"/path/to/template.odt\");",[18,9676,9677],{},"NodeList nodes = doc.getOfficeBody().getElementsByTagName(OdfTextUserFieldDecl.ELEMENT_NAME.getQName());",[18,9679,9680],{},"for (int i = 0; i \u003C nodes.getLength(); i++) {",[18,9682,9683],{},"OdfTextUserFieldDecl element = (OdfTextUserFieldDecl) nodes.item(i);",[18,9685,9686],{},"if (values.containsKey(element.getTextNameAttribute())) {",[18,9688,9689],{},"element.setOfficeStringValueAttribute(values.get(element.getTextNameAttribute()));",[18,9691,9692],{},"}",[18,9694,9692],{},[18,9696,9697],{},"doc.save(\"/path/to/result.odt\");`",[18,9699,9700],{},"When running the code above, the value in the document is replaced with the value set programmatically.",[30,9702,2765],{"id":2764},[18,9704,9705],{},"So far we are running code using ODFDOM for document generation successfully in two larger projects that have been\ndeveloped recently. We believe that ODFDOM will help us delivering additional value for our customers with less\ndevelopment effort.",{"title":43,"searchDepth":57,"depth":57,"links":9707},[9708,9709,9710,9711],{"id":9589,"depth":63,"text":9590},{"id":9616,"depth":63,"text":9617},{"id":9643,"depth":63,"text":9644},{"id":2764,"depth":63,"text":2765},[403,404],"2010-06-13T17:57:40","Generating documents from data that is managed by a web application is a quite common need. Think about letters that are\\ngenerated for a customer relationship management system or bills that are to be send for membership fees. For corporate\\nidentity reasons you don’t want these documents to look like generated from a plain text file but you want to have\\nlogos, tables, address labels and so on.","https://synyx.de/blog/template-based-document-generation-using-odfdom/",{},"/blog/template-based-document-generation-using-odfdom",{"title":9562,"description":9571},"blog/template-based-document-generation-using-odfdom",[9721,42,9616,9722],"document-management","openoffice-org","Generating documents from data that is managed by a web application is a quite common need. Think about letters that are generated for a customer relationship management system or bills…","s3AA3WrDYmRY0S6MePU2SvOKGaEOPjNDiiAX_h4Pn5U",[9726,9728,9730,9733,9735,9738,9741,9744,9745,9748,9751,9754,9757,9760,9763,9766,9768,9771,9774,9777,9780,9783,9785,9788,9791,9794,9797,9799,9801,9804,9807,9810,9813,9816,9819,9822,9825,9827,9829,9832,9835,9838,9841,9844,9847,9850,9852,9855,9858,9860,9863,9866,9869,9872,9875,9877,9880,9882,9885,9887,9890,9893,9896,9899,9902,9905,9908,9910,9913,9915,9918,9921,9924,9927,9930,9933,9935,9938,9941,9944,9947,9950,9953,9956,9959,9962,9965,9968,9971,9973,9976,9979,9982,9985,9988,9991,9994,9997,10000,10002,10005,10008,10011,10014,10016,10018,10021,10024,10027,10030,10033,10035,10037,10040,10043,10046,10049,10052,10055,10058,10061,10064,10067,10070,10073,10076,10079,10082,10084,10087,10088,10091,10094,10097,10100,10103,10106,10109,10112,10115,10118,10121],{"slug":1180,"name":9727},"Jennifer Abel",{"slug":3489,"name":9729},"Otto Allmendinger",{"slug":9731,"name":9732},"antony","Ben Antony",{"slug":2889,"name":9734},"Joachim Arrasz",{"slug":9736,"name":9737},"bauer","David Bauer",{"slug":9739,"name":9740},"bechtold","Janine Bechtold",{"slug":9742,"name":9743},"boersig","Jasmin Börsig",{"slug":7138,"name":6827},{"slug":9746,"name":9747},"buchloh","Aljona Buchloh",{"slug":9749,"name":9750},"burgard","Julia Burgard",{"slug":9752,"name":9753},"caspar-schwedes","Caspar Schwedes",{"slug":9755,"name":9756},"christina-schmitt","Christina Schmitt",{"slug":9758,"name":9759},"clausen","Michael Clausen",{"slug":9761,"name":9762},"contargo_poetzsch","Thomas Pötzsch",{"slug":9764,"name":9765},"damrath","Sebastian Damrath",{"slug":5570,"name":9767},"Markus Daniel",{"slug":9769,"name":9770},"dasch","Julia Dasch",{"slug":9772,"name":9773},"denman","Joffrey Denman",{"slug":9775,"name":9776},"dfuchs","Daniel Fuchs",{"slug":9778,"name":9779},"dobler","Max Dobler",{"slug":9781,"name":9782},"dobriakov","Vladimir Dobriakov",{"slug":9784,"name":9784},"dreiqbik",{"slug":9786,"name":9787},"dschaefer","Denise Schäfer",{"slug":9789,"name":9790},"dschneider","Dominik Schneider",{"slug":9792,"name":9793},"duerlich","Isabell Duerlich",{"slug":9795,"name":9796},"dutkowski","Bernd Dutkowski",{"slug":9798,"name":9798},"eifler",{"slug":9,"name":9800},"Tim Essig",{"slug":9802,"name":9803},"ferstl","Maximilian Ferstl",{"slug":9805,"name":9806},"fey","Prisca Fey",{"slug":9808,"name":9809},"frank","Leonard Frank",{"slug":9811,"name":9812},"franke","Arnold Franke",{"slug":9814,"name":9815},"frischer","Nicolette Rudmann",{"slug":9817,"name":9818},"fuchs","Petra Fuchs",{"slug":9820,"name":9821},"gari","Sarah Gari",{"slug":9823,"name":9824},"gast","Gast",{"slug":4801,"name":9826},"Johannes Graf",{"slug":1374,"name":9828},"Daniela Grammlich",{"slug":9830,"name":9831},"guthardt","Sabrina Guthardt",{"slug":9833,"name":9834},"haeussler","Johannes Häussler",{"slug":9836,"name":9837},"hammann","Daniel Hammann",{"slug":9839,"name":9840},"heetel","Julian Heetel",{"slug":9842,"name":9843},"heft","Florian Heft",{"slug":9845,"name":9846},"heib","Sebastian Heib",{"slug":9848,"name":9849},"heisler","Ida Heisler",{"slug":1662,"name":9851},"Patrick Helm",{"slug":9853,"name":9854},"herbold","Michael Herbold",{"slug":9856,"name":9857},"hofmann","Peter Hofmann",{"slug":7061,"name":9859},"Florian Hopf",{"slug":9861,"name":9862},"jaud","Alina Jaud",{"slug":9864,"name":9865},"jayasinghe","Robin De Silva Jayasinghe",{"slug":9867,"name":9868},"jbuch","Jonathan Buch",{"slug":9870,"name":9871},"junghanss","Gitta Junghanß",{"slug":9873,"name":9874},"kadyietska","Khrystyna Kadyietska",{"slug":7522,"name":9876},"Marc Kannegiesser",{"slug":9878,"name":9879},"karoly","Robert Károly",{"slug":7328,"name":9881},"Katja Arrasz-Schepanski",{"slug":9883,"name":9884},"kaufmann","Florian Kaufmann",{"slug":3383,"name":9886},"Mike Kesler",{"slug":9888,"name":9889},"kirchgaessner","Bettina Kirchgäßner",{"slug":9891,"name":9892},"klem","Yannic Klem",{"slug":9894,"name":9895},"klenk","Timo Klenk",{"slug":9897,"name":9898},"knell","Tobias Knell",{"slug":9900,"name":9901},"knoll","Anna-Lena Knoll",{"slug":9903,"name":9904},"knorre","Matthias Knorre",{"slug":9906,"name":9907},"koenig","Melanie König",{"slug":2799,"name":9909},"Thomas Kraft",{"slug":9911,"name":9912},"krupicka","Florian Krupicka",{"slug":2394,"name":9914},"Christian Kühn",{"slug":9916,"name":9917},"lange","Christian Lange",{"slug":9919,"name":9920},"larrasz","Luca Arrasz",{"slug":9922,"name":9923},"leist","Sascha Leist",{"slug":9925,"name":9926},"lihs","Michael Lihs",{"slug":9928,"name":9929},"linsin","David Linsin",{"slug":9931,"name":9932},"maniyar","Christian Maniyar",{"slug":1438,"name":9934},"Björnie",{"slug":9936,"name":9937},"martin-koch","Martin Koch",{"slug":9939,"name":9940},"matt","Tobias Matt",{"slug":9942,"name":9943},"mennerich","Christian Mennerich",{"slug":9945,"name":9946},"menz","Alexander Menz",{"slug":9948,"name":9949},"meseck","Frederick Meseck",{"slug":9951,"name":9952},"messner","Oliver Messner",{"slug":9954,"name":9955},"michael-ploed","Michael Plöd",{"slug":9957,"name":9958},"mies","Marius Mies",{"slug":9960,"name":9961},"mihai","Alina Mihai",{"slug":9963,"name":9964},"moeller","Jörg Möller",{"slug":9966,"name":9967},"mohr","Rebecca Mohr",{"slug":9969,"name":9970},"moretti","David Moretti",{"slug":2525,"name":9972},"Sven Müller",{"slug":9974,"name":9975},"muessig","Alexander Müssig",{"slug":9977,"name":9978},"neupokoev","Grigory Neupokoev",{"slug":9980,"name":9981},"nussbaecher","Carmen Nussbächer",{"slug":9983,"name":9984},"ochs","Pascal Ochs",{"slug":9986,"name":9987},"oelhoff","Jan Oelhoff",{"slug":9989,"name":9990},"oengel","Yasin Öngel",{"slug":9992,"name":9993},"oezsoy","Enis Özsoy",{"slug":9995,"name":9996},"posch","Maya Posch",{"slug":9998,"name":9999},"ralfmueller","Ralf Müller",{"slug":10001,"name":10001},"redakteur",{"slug":10003,"name":10004},"reich","Michael Reich",{"slug":10006,"name":10007},"reinhard","Karl-Ludwig Reinhard",{"slug":10009,"name":10010},"rmueller","Rebecca Müller",{"slug":10012,"name":10013},"rosum","Jan Rosum",{"slug":10015,"name":10015},"rueckert",{"slug":5633,"name":10017},"Sascha Rüssel",{"slug":10019,"name":10020},"sauter","Moritz Sauter",{"slug":10022,"name":10023},"schaefer","Julian Schäfer",{"slug":10025,"name":10026},"scherer","Petra Scherer",{"slug":10028,"name":10029},"schlicht","Anne Schlicht",{"slug":10031,"name":10032},"schmidt","Jürgen Schmidt",{"slug":2057,"name":10034},"Tobias Schneider",{"slug":6060,"name":10036},"Benjamin Seber",{"slug":10038,"name":10039},"sommer","Marc Sommer",{"slug":10041,"name":10042},"speaker-fels","Jakob Fels",{"slug":10044,"name":10045},"speaker-gierke","Oliver Gierke",{"slug":10047,"name":10048},"speaker-krupa","Malte Krupa",{"slug":10050,"name":10051},"speaker-mader","Jochen Mader",{"slug":10053,"name":10054},"speaker-meusel","Tim Meusel",{"slug":10056,"name":10057},"speaker-milke","Oliver Milke",{"slug":10059,"name":10060},"speaker-paluch","Mark Paluch",{"slug":10062,"name":10063},"speaker-schad","Jörg Schad",{"slug":10065,"name":10066},"speaker-schalanda","Jochen Schalanda",{"slug":10068,"name":10069},"speaker-schauder","Jens Schauder",{"slug":10071,"name":10072},"speaker-unterstein","Johannes Unterstein",{"slug":10074,"name":10075},"speaker-wolff","Eberhard Wolff",{"slug":10077,"name":10078},"speaker-zoerner","Stefan Zörner",{"slug":10080,"name":10081},"stefan-belger","Stefan Belger",{"slug":5719,"name":10083},"Roland Steinegger",{"slug":10085,"name":10086},"stern","sternchen synyx",{"slug":1654,"name":1654},{"slug":10089,"name":10090},"szulc","Mateusz Szulc",{"slug":10092,"name":10093},"tamara","Tamara Tunczinger",{"slug":10095,"name":10096},"theuer","Tobias Theuer",{"slug":10098,"name":10099},"thieme","Sandra Thieme",{"slug":10101,"name":10102},"thies-clasen","Marudor",{"slug":10104,"name":10105},"toernstroem","Olle Törnström",{"slug":10107,"name":10108},"ullinger","Max Ullinger",{"slug":10110,"name":10111},"ulrich","Stephan Ulrich",{"slug":10113,"name":10114},"wagner","Stefan Wagner",{"slug":10116,"name":10117},"weigel","Andreas Weigel",{"slug":10119,"name":10120},"werner","Fabian Werner",{"slug":10122,"name":10123},"wolke","Sören Wolke",["Reactive",10125],{"$scookieConsent":10126,"$ssite-config":10128},{"functional":10127,"analytics":10127},false,{"_priority":10129,"env":10133,"name":10134,"url":10135},{"name":10130,"env":10131,"url":10132},-10,-15,0,"production","nuxt-app","https://synyx.de",["Set"],["ShallowReactive",10138],{"category-open-source-blog":-1,"authors":-1},"/blog/kategorien/open-source-blog"]