{"id":20877456,"url":"https://github.com/t1/pomx","last_synced_at":"2025-05-12T16:30:40.481Z","repository":{"id":142921372,"uuid":"82270068","full_name":"t1/pomx","owner":"t1","description":"Extended Maven POM file format","archived":false,"fork":false,"pushed_at":"2022-01-01T10:25:31.000Z","size":108,"stargazers_count":8,"open_issues_count":0,"forks_count":1,"subscribers_count":4,"default_branch":"master","last_synced_at":"2023-10-20T23:19:19.605Z","etag":null,"topics":["build-tool","maven","maven-extension","polyglot","pom","pomx-profile","xml","xsd"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/t1.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2017-02-17T07:32:34.000Z","updated_at":"2023-10-20T23:19:20.009Z","dependencies_parsed_at":"2023-04-27T17:55:35.389Z","dependency_job_id":null,"html_url":"https://github.com/t1/pomx","commit_stats":null,"previous_names":[],"tags_count":0,"template":null,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/t1%2Fpomx","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/t1%2Fpomx/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/t1%2Fpomx/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/t1%2Fpomx/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/t1","download_url":"https://codeload.github.com/t1/pomx/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":225141812,"owners_count":17427362,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["build-tool","maven","maven-extension","polyglot","pom","pomx-profile","xml","xsd"],"created_at":"2024-11-18T06:57:05.163Z","updated_at":"2024-11-18T06:57:05.850Z","avatar_url":"https://github.com/t1.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Xml Is Not The Problem\n\nThere's a lot of complaining about [Maven](http://maven.apache.org) being too verbose.\nThe Maven developers listened and started [Polyglot Maven](https://github.com/takari/polyglot-maven/tree/master/polyglot-xml)\nto address the issue.\nThey support Groovy, Scala, Ruby, Yaml or other file formats, and they may be beneficial to some people,\nbut I don't think that XML is the problem, so those other file formats are not guaranteed to be a cure.\n\nXML has reputation for being verbose, because it requires you to repeat the name of the opening tag when closing it.\nThis actually does add a bit of verbosity, but it's also quite useful to orient in large blocks.\nXML also supports attributes, which actually require a little bit less overhead than JSON!\nMaven POM files just never use them!\nInstead of expressing a dependency like this:\n\n```xml\n\u003cdependency\u003e\n    \u003cgroupId\u003ech.qos.logback\u003c/groupId\u003e\n    \u003cartifactId\u003elogback-classic\u003c/artifactId\u003e\n    \u003cversion\u003e1.2.1\u003c/version\u003e\n\u003c/dependency\u003e\n```\n\nA POM could use attributes like this:\n\n```xml\n\u003cdependency groupId=\"ch.qos.logback\" artifactId=\"logback-classic\" version=\"1.2.1\"/\u003e\n```\n\nThe Polyglot project has an XML format that goes exactly this way.\nThe other file formats use an even more compact format by simply separating the GAV fields with colons.\nThis is less explicit, but the GAV coordinates are ubiquitous enough, nowadays, so everybody will easily understand them.\nSuch a compact notation could be used in XML, too, and it would look like this:\n\n```xml\n\u003cdependency\u003ech.qos.logback:logback-classic:1.2.1\u003c/dependency\u003e\n```\n\nWhile this makes the syntax more concise, the real benefit other languages _can_ provide (if used properly),\nis to reduce the repetition in you build files - Don't Repeat Yourself or DRY.\nBy leveraging reuse, build files don't just get more concise,\nthey also get more uniform (by reducing the snowflake effect: every snow crystal is different)\nand more expressive (if you can find a solid abstraction with a clear name).\nI.e. if you want e.g. a Java EE 7 WAR, you should only specify that this is what you want,\nand the know-how required to build it, the dependencies, the Java compiler setting, the properties, etc.\nis expressed once-and-only-once in a file in the repository. We can do that with XML.\nPOMX does so by allowing profiles to be defined in Maven repository files.\n\nXml is not the problem.\n\n\n## Quick-Start\n\nAdd a directory `.mvn` to your project.\nCreate a file `extensions.xml` in `.mvn` containing:\n\n```xml\n\u003c?xml version=\"1.0\" encoding=\"UTF-8\"?\u003e\n\u003cextensions\u003e\n    \u003cextension\u003e\n        \u003cgroupId\u003ecom.github.t1\u003c/groupId\u003e\n        \u003cartifactId\u003epomx\u003c/artifactId\u003e\n        \u003cversion\u003eVERSION\u003c/version\u003e\n    \u003c/extension\u003e\n\u003c/extensions\u003e\n```\n\nCopy your `pom.xml` to `pomx.xml` and stop using the old file... it will be overwritten with every build.\nIt's required by your IDE and other tools and Maven will install and deploy it normally,\nso Repository managers etc. can use it.\nYou don't have to put it under version control, but a fresh checkout would not be properly recognized by your IDE;\nand the generated `pom.xml` is the only place to see build differences when external SNAPSHOT profiles change.\nSo it's a good practice to check the `pom.xml` into your SCM.\n\n\n## Setup\n\nI took a look at the code of the Polyglot project, but I absolutely need a classic POM to be generated\nfor other tools to work correctly; Polyglot still works on this.\nAnd my code is much smaller and easier to understand.\n\nThe XSD is in `https://raw.githubusercontent.com/t1/pomx/master/src/main/resources/schemas/pom-5.0.0.xsd`\nand I boldly name the namespace `urn:xsd:maven:pomx:5.0.0`.\n\n\n## Features\n\n### Include `modelVersion` \u0026 New XSD\n\nold:\n\n```xml\n\u003cproject xmlns=\"http://maven.apache.org/POM/4.0.0\"\u003e\n    \u003cmodelVersion\u003e4.0.0\u003c/modelVersion\u003e\n\u003c/project\u003e\n```\n\nnew:\n\n```xml\n\u003cproject xmlns=\"urn:xsd:maven:pomx:5.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"urn:xsd:maven:pomx:5.0.0 https://raw.githubusercontent.com/t1/pomx/master/src/main/resources/schemas/pom-5.0.0.xsd\"\u003e\n\u003c/project\u003e\n```\n\n\n### Compact GAV with packaging as element\n\nold:\n\n```xml\n\u003cproject\u003e\n    \u003cgroupId\u003ecom.github.t1\u003c/groupId\u003e\n    \u003cartifactId\u003edeployer\u003c/artifactId\u003e\n    \u003cversion\u003e2.7.3-SNAPSHOT\u003c/version\u003e\n    \u003cpackaging\u003ewar\u003c/packaging\u003e\n\u003c/project\u003e\n```\n\nnew:\n\n```xml\n\u003cwar\u003ecom.github.t1:deployer:2.7.3-SNAPSHOT\u003c/war\u003e\n```\n\nschema: `\u003cpackaging\u003egroupId:artifactId:version\u003c/packaging\u003e`\nor: `\u003cpackaging\u003egroupId:artifactId:classifier:version\u003c/packaging\u003e`\n\n\n### Compact GAV of Build Plugins\n\nold:\n\n```xml\n\u003cplugin\u003e\n    \u003cgroupId\u003eorg.apache.maven.plugins\u003c/groupId\u003e\n    \u003cartifactId\u003emaven-jar-plugin\u003c/artifactId\u003e\n    \u003cversion\u003e2.4\u003c/version\u003e\n    \u003cconfiguration\u003e\n        \u003carchive\u003e\n            \u003caddMavenDescriptor\u003efalse\u003c/addMavenDescriptor\u003e\n        \u003c/archive\u003e\n    \u003c/configuration\u003e\n\u003c/plugin\u003e\n```\n\nnew:\n\n```xml\n\u003cplugin id=\"org.apache.maven.plugins:maven-jar-plugin:2.4\"\u003e\n    \u003cconfiguration\u003e\n        \u003carchive\u003e\n            \u003caddMavenDescriptor\u003efalse\u003c/addMavenDescriptor\u003e\n        \u003c/archive\u003e\n    \u003c/configuration\u003e\n\u003c/plugin\u003e\n```\n\n\n### Compact Dependency Management\n\nold:\n\n```xml\n    \u003cdependencyManagement\u003e\n        \u003cdependencies\u003e\n            \u003cdependency\u003e\n                \u003cgroupId\u003eorg.jboss.arquillian\u003c/groupId\u003e\n                \u003cartifactId\u003earquillian-bom\u003c/artifactId\u003e\n                \u003cversion\u003e1.1.11.Final\u003c/version\u003e\n                \u003cscope\u003eimport\u003c/scope\u003e\n                \u003ctype\u003epom\u003c/type\u003e\n            \u003c/dependency\u003e\n        \u003c/dependencies\u003e\n    \u003c/dependencyManagement\u003e\n```\n\nnew:\n\n```xml\n    \u003cdependencyManagement\u003e\n        \u003cpom\u003eorg.jboss.arquillian:arquillian-bom:1.1.11.Final\u003c/pom\u003e\n    \u003c/dependencyManagement\u003e\n```\n\n\n### Compact Dependencies Grouped By Scope\n\nold:\n\n```xml\n    \u003cdependencies\u003e\n        \u003cdependency\u003e\n            \u003cgroupId\u003ejavax\u003c/groupId\u003e\n            \u003cartifactId\u003ejavaee-api\u003c/artifactId\u003e\n            \u003cversion\u003e7.0\u003c/version\u003e\n            \u003cscope\u003eprovided\u003c/scope\u003e\n        \u003c/dependency\u003e\n    \u003c/dependencies\u003e\n```\n\nnew:\n\n```xml\n    \u003cdependencies\u003e\n        \u003cprovided\u003e\n            \u003cjar\u003ejavax:javaee-api:7.0\u003c/jar\u003e\n        \u003c/provided\u003e\n    \u003c/dependencies\u003e\n```\n\n`optional`:\n```xml\n\u003cjar optional=\"true\"\u003ejavax:javaee-api:7.0\u003c/jar\u003e\n```\n\n\n### External Profiles\n\nProfiles can be stored in a repository and referenced in the POMX:\n\n```xml\n\u003cprofile\u003ejavax:javaee-api:7.0\u003c/profile\u003e\n```\n\nThe profile xml file is resolved like a maven dependency, included into the POM, and activated when run.\n\nThis feature is similar to [maven tiles](https://github.com/repaint-io/maven-tiles).\n\nEven though it is a `profile`, the file can have a `project` namespace like a `pomx`, i.e.:\n\n```xml\n\u003c?xml version=\"1.0\" encoding=\"UTF-8\" ?\u003e\n\u003cproject xmlns=\"urn:xsd:maven:pomx:5.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"urn:xsd:maven:pomx:5.0.0 https://raw.githubusercontent.com/t1/pomx/master/src/main/resources/schemas/pom-5.0.0.xsd\"\u003e\n    \u003cpom\u003emy.group:my.artifact:1.0\u003c/pom\u003e\n    ...\n\u003c/project\u003e\n```\n\nIn the generated POM, this profile would have the `\u003cid\u003emy.group:my.artifact\u003c/id\u003e` so you can disable it like this:\n\n`mvn clean install -P-my.group:my.artifact`\n\n(The colon was chosen for clarity, as '.' and '-' are too common in group and artifact ids)\n\nNote: This will probably change in the future! As the profile may have to be merged completely.\n\nSome profile elements are removed and not copied into the target profile: `modelVersion`, `groupId`, `artifactId`, `version`, `packaging`, `name`, `description`\n\nSome profile elements are merged into the target `project`, not copied into the target profile: `licenses`, `repositories`, `distributionManagement`, `scm`, and `profiles`\nYou can't deactivate these elements by deactivating the profile.\n\nFinally, a property `\u003cgroupId\u003e.\u003cartifactId\u003e.version` is set to the version of every external profile.\nFor a use case see the [t1-profile](https://github.com/t1/pomx-profile-t1).\n\n\n# Quirks\n\nThe order of the elements in a POM xml file is normally free.\nBut I wanted to have multiple `profile` elements on the top level,\nand XSDs don't seem to allow `maxOccurs=\"unbound\"` for `xs:any`, so I provisionally used `xs:sequence`,\nwhich requires the elements to have a fixed order.\nI'm not an XSD expert, so I had planned to learn how to fix this,\nbut before I did, I thought that this might be even better.\nIt makes orientation in big POMs easier, so ordered the elements supposedly usefully, and still like it.\nIt's irritating at times, esp. when you migrate to the new format, but I won't investigate any further.\n\n\n# Major TODOs\n\n### Download External Profiles\n\nExternal profiles are yet expanded only from your local repository (`~/.m2/repository`).\nSo you'll have to fetch them manually before you start the first build:\n\n`mvn dependency:get -DgroupId=my.group -DartifactId=my.artifact -Dpackaging=xml -Dversion=1.0`\n\n### Compensate For External Changes\n\nE.g. the maven release plugin manipulates the `pom.xml`, not the source of truth `pomx`, by setting the version, e.g., `1.2.3-SNAPSHOT` to `1.2.3`. When it starts the actual build, pomx overwrites the `pom.xml` reverting the version change.\nThe build won't properly run.\n\nIm currently unsure how to fix it. We could hook into the plugins, or we could check the change date and when the pom is newer than the pomx, we could create a diff and apply it to the pomx.\n\nAs a manual workaround, I do the following steps:\n- disable the extension (renaming the `.mvn` directory is generally good enough)\n- commit my changes\n- do the release\n- re-enable the extension\n- manually update my `pomx.xml` (mostly update the version)\n- commit these changes\n\n# Ideas\n\n- Scan for `modules`, i.e. look at all direct directories, if they include a `pomx.xml`,\nand add them to the `modules` in the parent. This is then recursive for those modules.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ft1%2Fpomx","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ft1%2Fpomx","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ft1%2Fpomx/lists"}