Wednesday, January 16, 2008

Why Grails doesn't use Maven

Update: As of Grails 1.1, Grails now provides Maven support. My personal feelings towards Maven haven't changed much, it is in my view basically the EJB2 of build tools. However, if you want to use Maven with Grails that is now a possiblity.

In his post entitled "Grails - The Good, The Bad and the Ugly", Jonas has some nice praise for Grails, his main beef is that it is not built on Maven.

So I wanted to clarify why exactly we chose not use Maven (by default) and the explanation is there for all to see in Jonas' first example of creating a Grails application vs creating a Maven project:

Instead of

grails create-app name

could be just

mvn archetype:create -U \
-DarchetypeGroupId=net.liftweb \
-DarchetypeArtifactId=lift-archetype-blank \
-DarchetypeVersion=0.4 \
-DremoteRepositories=http://scala-tools.org/repo-releases \
-DgroupId=your.proj.gid -DartifactId=your-proj-id

My goodness, what a mouthful the Maven example is. There is a common acronym in the open source world called RTFM (read the *ing manual), when a user asks a question on a mailing list and the "experts" respond by pointing them to the place in the manual.

For me Grails is all about dramatically simplifying, and reducing the cases where you have to RTFM. Grails wraps popular Java libraries like Spring, Hibernate, Sitemesh and Quartz and does a damn good job of hiding that complexity.

I'm not saying you never have to RTFM manual, but once you have learnt Grails the cases where you need to are few and far between and for simple things like creating an application, once you know how, you never need to go back. In other words Grails is all about simplifying Java EE.

Now Maven is the complete opposite of this. Why do I have to go and read their manual everytime I want to creating a project. I mean there is no way I will remember all that crap and their documentation is pretty appauling to begin with.

I think only Java people would be willing to accept a build system like Maven with all its complexities. Any other community would be like "what the hell is this?". For me Maven is the EJB2 of build systems: over complicated, over engineered and requiring an intelligent, code generating IDE just to work with it.

Having said all of that there are a good number of companies adopting Maven (god help them) and so I am not against having Maven support in Grails, but not by default. Arnaud from Octo has put together the excellent Maven Tools for Grails project, which allows you to create a POM for a Grails application and integrates Grails with the Maven lifecycle. Maybe one day we will include it in Grails core by default as an optional extra if Arnaud is interested in that.

However, I feel there is no use putting Maven in by default, because I strongly believe that in the long term it will be replaced by better tools like Gant, Raven, or Buildr.

42 comments:

Martin Gilday said...

You make some good points about the current state of Maven. However for teams already dependant on Maven it is a barrier to entry to adopting Grails. I think buildr/raven support would be a good direction to head as then these teams can levarge their existing repositories, keeping their "legacy" systems using Maven and a new Grails project can use buildr.

landry said...

I absolutely agree with your opinion on Maven. Please keep this direction for Grails, no doubt your assumptions about Maven's successor will happen before Maven replaces Ant.

Kocka said...

Graeme,

I partially disagree with your post.

'grails create-app ' allready contains some information compared to 'mvn archetype:create'. Most importantly that this is going to be a _grails_ project an nothing else, you still need to specify this for mvn. Also there are some information that it simply does not handle, which is your identity. We could argue about this 'should the project store information about the developer' question, whatever, maven does so.

Laszlo

Anonymous said...

Being in a company where Octo pushed Maven, I can only agree. Watching colleagues spending days coming up with a deployable app is a real WTF experience.

Anonymous said...

Hmmm...if you were simply after simplifying the command line you could have just written a shell script to wrap some of the more lengthy maven calls. Then, you would have gotten all of the benefits of the maven model (dynamically keeping dependencies up to date plus the rest of the maven infrastructure).

Sounds to me like you were looking for a reason not to use maven...not a way to use it. Which is fine... just means that you haven't seen the light. :)

omartin said...

Well I have to disagree, all ASF projects used to have Ant, they have Maven now... There is a reason ;)

In my organization the only recognized standard for a Java application is EAR. With maven all I have to do is :

mvn ear

Tell me how I do this simple task with Grails... Btw I read the F** manual.

Graeme Rocher said...

@olive

ASF use maven because maven is Apache and they have to eat their own dog food

If you need dependency resolution from Maven repos you can use Ivy or Gant

As for EAR files since each Grails application represents a single web application (a WAR) it doesn't make sense to have a EAR command

Besides an EAR is just a JAR file containing JARs and WARs and its simple to write a top level build to do this, hell you could even use Maven for it if you want ;-)

Graeme Rocher said...

Also I would just like to say to all those "disagreeing" with my comments that again I am not against the idea of supporting Maven in Grails

Just not by default. For Grails 1.1 we plan to incoporate the Maven Tools for Grails project into Grails core.

Dustin Ted Whitney said...

Agreed!

Anonymous said...

Dudes, it's time to jump the fence and embrace Grails. Do not fear.

Unknown said...

In my experience, Maven adds additional complexity that is not outweighed by the benefit it brings over simpler systems like Ant. I am glad to see a major project like Grails pushing back against the drive toward Maven.

boomtown15 said...

I can't believe that people give up on Maven so easily. It is actually really simple if you follow the conventions. Ok, that first project setup is a bit rough and I agree the learning curve is a bit steep, but I believe the benefits outweigh this. Once you have one project all you have to do is copy a POM file and change a couple of settings. Then if you are smart you will create an automated procedure that sets the POM up asking the user a couple simple questions. Its really not that hard. Oh, and it handles dependencies beautifully. This is the main reason I went from Ant to Maven. I think people don't want to invest any time in learning something new so they give up instantly. Spend a little time and I think you would find out that its really pretty slick and there are many tools out there (Continuum, Archiva, Eclipse plug-ins) that aide in some of the command line terse entries.

Anonymous said...

Thanks for the smart decision to not use Maven.

I lost interest in Appfuse when it switched to Maven.

Anonymous said...

i use ivy + ant and that's quite
ok. "maven is ejb2 of buildsystems" ;-) nice metapher.

IMO one of the things grails could
improve in future is support for
ci-build of apps (hooks in buildsystem). first step to improvement could be to put grails-samples under different ci
(bamboo, cruisecontrol). grails-sample are neglect anyway.
they can be to grails, what grails is to groovy.

another point is, that grails- development in eclipse must get
more comfortable. many programmers (me too) are bound to eclipse by company convention. this is mainly
a groovy-eclipse-plugin task i know
...

Les said...

Not that it is pertinent to this post, but it never ceases to amaze me at the blow back against maven.

Maven has a higher initial learning curve, but the payoff is more simplicity as things get more complex.

Ant is the opposite. Ant is easy to get started, but when you start to get complex is becomes complicated (just try to keep up with netbeans ant files). In fact, the only reason you would ever need something like gant is because of the complexity of accomplishing those things in ant directly. Arguably, gant would not be ant based if all of the tasks were available in another library (ant core would become unnecessary overhead).

All the same...I love grails and am happy to see that it is supporting either build metaphor.

Anonymous said...

While I do agree with you, that maven can be complex, is over engineered and lacks good documentation, I still have a feeling, that maven is the best thing around.

I use maven each and every day, and yes, I bitch about it. But I have also tried to go back to ant (which I also know quite well), ... and it was a PAIN. Then, I saw how much I get from maven.

So, for now, I stick with maven. But am looking at other build tools, as they come out.

Things like raven and buildr, I don't believe much in. I think they are just trying to be an easier maven. But I think the underlying problem of automatic dependency resolution is really hard to solve.

Matt Raible said...

I started posting my comments here, but they got a bit long:

http://raibledesigns.com/rd/entry/re_why_grails_doesn_t

Unknown said...

I can build any maven project without reading instructions on how it builds. Can I do same way with Ant/Gant? Hell no!

Nutricherry Team said...

> I can build any maven project without reading instructions on how it builds.

> Can I do same way with Ant/Gant? Hell no!

However, you can build many grails applications without knowing a lot about it. Personally, I think it works fine the way it is, please don't complicate it for the simple cases.

Unknown said...
This comment has been removed by the author.
Unknown said...

If using archetype plugin is too complex for you then it doesn't mean that other developers experiencing the same.

Furthermore, the new project creation is not an everyday task. but project build is an everyday task.

I suggest you guys, who prefer ant over maven, to ask Cocoon contributers how easy it was when there was an Ant build? And compare with how it is now, with maven?

Graeme Rocher said...

I'm surprised the Cocoon guys were brave enough to continue with Maven given it caused such chaos for them:

http://bluxte.net/blog/2006-09/17-52-51.html

Anonymous said...

Graeme,
Your main objection against maven is (or was) the lack of good documentation, which then stirred a lot of frustration. Yes, the lack of proper maven docs was a real pain. Sometimes, it still is.

However, grails have (had) the same problem. The new docs of grails is great. But before that it was a real pain to figure out how to realize any non-trivial task. Especially, when the grails docs sometimes was not coherent, reflecting different versions.

What grails is missing from an enterprise point of view is friendly co-existence with Java community standards. I mean, it's time to move away from the underdog perspective and start using grails for real.

The directory structure of grails is fine for a Q&D webapp, but doesn't easily integrate in a bigger project with several modules, where grails 'simply is just a' web component.

Maven relies on configuration by convention - which grails do as well - but allows one to configure directories when the default layout is not appropriate. A first step for grails, would be this level of configurability. (Unless, this is already supported and I failed to RFTM ;-)

One drawback with the current directory structure is that it do not easily play nicely with a modern IDE, such as IDEA and Eclipse. Yes, I know IDEA has good support for groovy, but the grails support still left some to desire. And using eclipse to develop in grails is a joke. My point is, you end up with plenty of source directories to manage, instead of a clean source structure as one can see in maven. This layout has over time has become an appreciated project directory structure.

If it were possible to configure the 'conventions' of grails I believe it would be easier for friendly co-existence, with both IDEs and maven. Do not give up on the original grails spirit, but on the other hand do not fight against people actually starting to use grails professionally in multi-module projects.

I have been looking at the grails-maven plugin, but I'm not really satisfied with its goals. What's needed is a (small/focused) plugin that provide hooks to build the grails war artifact, as part of a larger build, and hooks for generating documentations suchs as test results, source and javadocs. Besides of that, I don't see the point of switching from 'grails create-domain-class' to 'mvn grails:create-domain-class'.

Another very big benefit of maven is the management of 3rd-party jars for a normal versioned project (svn/cvs/...). That means, never ever check in any jars. (Everybody that expirenced the opposite, knows exactly why) Using grails one always have to be very careful to ensure that not any generated files (or jars inside 'grails-proj/lib') slips into the VCS repo.

It would be so nice if I could just type 'mvn clean' at the top-level which then recurse down the modules and after that type 'svn commit ...'. Currently, having grails in a multi-module project means establishing exception procedures and instructions. It's like dealing with an obstinate teenager ;-) Hmm, sorry for that pitch. It's time for grails to grow up.
/jens

Anonymous said...

Hi

I believe that one of the BIGGEST strengths of Grails is convention over configuration just like RoR. The hugh advantage of this is that new developers to a project that know grails can start in a very familiar development environment.

If you start allowing people to define their own grails directory structure then that will totally F**kup the whole point of convention over configuration. I think the directory structure is fantastic as it is. I would like to see it extended to the css subdirectories too.

If you want to do your own configuration of a project then Grails is not for you. Go and use one of the many many java frameworks that allow this.

Antony Stubbs said...

"ASF use maven because maven is Apache and they have to eat their own dog food"
I think that is very short-sighted and pessimistic. Maven provide many many advantages over their old Ant system.
Would you want every ASF project create it's own build system ontop of Ant? This is what you have done for Grails.

"If you need dependency resolution from Maven repos you can use Ivy or Gant"
Maven is far far more than simply dependency resolution.

"As for EAR files since each Grails application represents a single web application (a WAR) it doesn't make sense to have a EAR command"
Most JavaEE projects are more than just a simple WAR. This is where EAR's come into play.

"Just not by default. For Grails 1.1 we plan to incorporate the Maven Tools for Grails project into Grails core."
I think that's really great! optional Tight integration of Maven into grails will really help a lot - much much better than having nothing.
However, IMO writing your simplified build layer on top of Maven would have been less 'Not Invented Here'.

"...Maven adds additional complexity..."
If you start off using Maven in a project, the complexity is entirely optional.

I used Ant on my last large Enterprise system, which had several projects and the Ant scripts got ridiculous. I believe that Maven would have nearly completely removed our build headaches.

I think jens really said it very well - I wish I'd read his post first ;) lol

Grails's own convention, breaks the convention Java Community is trying to move towards (~Maven).

p.s. - I love Grails and think you're doing an AMAZING job! Go G2!

________________________
http://stubbisms.wordpress.com/

Anonymous said...

Maven has improved much in its second release, but it's still not ergonomic. Imagine you want to have a .jar - "mvn jar", awesome! But, now imagine you want to have a simple Manifest into the jar that tells which is the main class - 20 lines of XML in the POM! That kicks my ass!

Unknown said...

"ASF use maven because maven is Apache and they have to eat their own dog food"
This is wrong, projects at ASF don't "have to" use any specific build system. Some are using Ant or Ant+Ivy, some Maven, some Buildr (well, at least Buildr itself, which is not yet a full blown ASF project).

IMHO, one of the main reason many Java open source projects use maven 2 is because it's currently the only available "ready to use" build system. Ant is not a build system, it's a build tool, with which you can create your own build system.

Very often people say it's quicker to start with Ant, but it depends what you need. If you need a build system which provides compilation only, it's probably quicker with Ant. But if you want compilation, tests, packaging, code coverage, dependency management, and others common build system features, I think using Maven is faster than creating your own Ant build script.

So, am I a Maven advocate? Yes and no. I like the idea behind Maven, being able to build a project in a standard way is really neat. What I dislike is the lack of documentation, flexibility and robustness, and that there's just too much black magic.

And these points are so important IMHO that I see many real life projects still preferring to use a home made Ant based build system. And you can create rock solid and flexible build systems with Ant, but you need to treat your build system as any piece of software: carefully designed for maintenance and robustness.

hohonuuli said...

For a Grails developer, I'm surprised about your stance on Maven. After all Maven is pushing 'convention over configuration' in a build tool; isn't that what Grails is focused on...'convention over configuration'

I've used make, ant, maven2, shell scripts, gant and buildr for projects. Pretty much all my projects are now Maven. And this IS a barrier for Grails. I have a number of projects that could benefit from grails but shoehorning them into the Grails project structure isn't really an option. Grails is just a bit too opinionated that way.

Anyway, the point your missing in your example is that the user doesn't have to install and configure anything (other than Maven) to setup, build and run the liftweb project. Maven does it ALL for you. With Grails the user has to install and configure Grails on the build machine.

Also, just for edification, here's some nice examples of why Maven it handy:

1) If I want to add groovy code to my project, I just add a few lines of XML to my POM and Maven compiles the groovy code and adds it the completed jar. See http://mojo.codehaus.org/groovy/guide-groovy-development.html

2) Want to run your maven webapp project in a server (ala grails run-app). No problem, add 4 lines of XML to my POM and I can now execute mvn jetty:run See http://cwiki.apache.org/WICKET/maven-jetty-plugin.html

3) Need to update the version of groovy your Maven project uses. It only takes a couple of keystokes.

jonas said...

Graeme,

I made a comparative between gant, raven and buildr and maven.

I hope it will be helpful:
http://jonasfagundes.com/blog/2008/01/the-misunderstood-maven.

Cheers,
Jonas Fagundes

J. Suereth said...

Sorry I'm late on posting replies, but I've been investigating Maven/Grails support and have been disappointed so far.

I'd like to clear a few misconceptions about Maven. Perhaps for a smaller company where you need to get something done very quickly, maven is a bad initial investment. However, once you've copied and pasted your ANT build files for the 10th time, you need to start thinking about re-use and maintenance of these scripts. ASF uses Maven because they can specify a "company" pom that all projects can derive from. This POM specifies all the ASF settings that do not need to be in all the individual projects. At our company, we've found this to be invaluable. Starting a new project is as simple as

<project>
<!-- project metadata -->
<parent>
<!-- parent metadata -->
</parent>
</project>

In fact, we even have the parent pom detect language usage, such as Scala, Groovy or Javascript and add dependencies where needed. The biggest buy for Maven is the Object-Oriented build system. I've seen GANT and it's much nicer than ANT, but it still doesn't offer me that Object Orientation. If we want to follow a DRY principle, I think OO build-files are the next step in build tools.

If something comes along to replace maven that gives me the ability to factor out common "company" build info (e.g. Continous build info, Deployment strategies, Project Management Analysis tools [PMD, Cobertura, etc.) then I will happily jump on the bandwagon and never touch XML again. However, right now Maven is the emerging build tool for the Java platform. It has a ton of great plugins, a ton of features and an OO build structure. I can set a lot of stuff up once and forget about it.

Using other tools, such as Continuum and Archiva can really enhance the Maven experience. We've specified in Archiva a bunch of repositories to "proxy" (e.g. spring, codehaus and the maven central). Combined with adding our own projects into the company Archiva server, I can now easily find company libraries with source and javadocs attached, and begin to use nightly-snapshots from other developers in the company. This has really increased code-reuse for us by making it simpler to pull in another's code. (just depend on it). It's my opinion that Reuse only happens if it's viewed as the laziest solution to a problem, and Maven/Archiva/Continuum have helped us with that.

Anonymous said...

Maven doesn't have to be complicated and you don't *HAVE* to use the archetype system. Why not have:

mvn grails:create-app name

And I'm talking about more than the current grails plugin's approach of just delegating to Grails and requiring a grailsHome property to be set.

I'm talking having the grails plugin part of the maven repository so that the above command would download Grails if you don't already have it installed and then delegate to the normal grails functionality.

Surely that is an advantage over the approach of having to download Grails on your own, having to make sure every team has the same version of Grails, etc. Plus it gives Grails a built in hook to pull in maven repository dependencies instead of having to include them in the Grails distribution.

Look, I agree that maven has it's shortcomings. But it also has significant benefits when it comes to uniformity of projects for an enterprise (custom build scripts inevitably lead to every project being slightly different which causes major headaches for continuous build systems among other things).

And there's no reason why you can't have both a pom.xml that covers the maven basics while at the same time using GANT to provide more advanced features that would be difficult to do in maven (and you could just have the grails plugin delegate to the Grails GANT system to do this).

And it would be ideal to be able to use the maven "site" target and the various maven reporting targets (e.g. coverage, findbugs/PMD, checkstyle, etc) to generate reports on each Grails app. This is something that Grails currently lacks and I don't see why Grails should reinvent the wheel to provide this support.

In short, I sincerely hope that you have a change of heart regarding supporting Maven as part of the core Grails system.

Christian Tzolov said...

The lack of maven support IS a barrier for our team as well.
Having all our projects organized around Maven's ecosystem makes it less attractive for us to try and to integrate tools that lacks such functionality.

Franz See said...

IMHO, maven is all about management.

Policies, guidelines, and bureaucracies are a PITA if you have a small project/team. But once you have a big project/team, build management is a savior.

Re Project size:
That's why you would hear people complain about how hard it is do some build task 'A' in Maven. But hear people praise about how easy it is to manage their builds with Maven.

If you have a small project, worrying about some build task 'A' eats a whole lot of time. But if you're working on a huge project, worrying about 'A' is worth it if 'B' to 'Z' is taken care of.

Moreover, once a maven module grows too big, it is easy to create sub-modules. Thus you create small easily maintainable components (not just build-wise but code-wise as well).

Re Team size:
Also, it is easy to add people to work on project built on maven (or have people work on different modules). Those additional personnel would only have to worry about the code base and not the build.

And since it's easy to create modules in maven, you get small code base to work with.


Misc:
Lastly, another issue some people have with maven is on how hard it is do migrate to Maven. Yes, it's a PITA and I don't think there's any claim that it is not. Furthermore, the bigger your project is, the harder it is to migrate to Maven. - this one is a sad fact of life, and the only consolation here is that you only need to migrate once :-)

Anonymous said...

Did you consider Gradle?

Anonymous said...

yes, i am especially missing the dependeny management and report part of maven.

if you grasped mavens concept and can rely on plugins quality i don't perceive it more complicated as other build systems. in fact things are getting much easier and you get reports with nearly no more work for free. to summarize: the tooling is not more complex but you really need to understand maven's philosophy and concept to get it going.

for grails fortunately there are maven tools for grails :)

Anonymous said...

"Why Grails doesn't use Maven" shows how narrow a view the author possesses. Probably you think Java is all about Web application development and Grails is therefore all a programmer needs?

FYI, we use Maven to build everything - from Java-based high performance computing projects (that has nothing to do with the web), MMORPG game engines, Flash/Flex-based Rich Internet Applications to Web Services. Take RIA for example, we use Maven to create our project directory structure that conforms to our own SVN convention, under which we use our own Flex archetype to create client side of the RIA and we use Grails or BlazeDS archetypes to create the server side.

It would be nice to have Maven as the universal build solution for our systems. By the way, Maven doesn't just handle JAR/EAR/WAR, we use it to build SWC/SWF. You think Grails can handle that?

Don't be narrow-minded - different people have different needs. There is a good reason why we need Grails/Maven combination to work.

GrOG said...

Is "mvn archetype:generate" simple enough?

~ simple minds in simple words ~ said...

i love to see simple command from grails. if i am a beginner and i need to build web application with grails... i don't want to waste my time for learning maven just for building project.

I love to see Grails simplify the problem of over complexity in J2EE.
I am curious why so many people love complexity over simplicity :)

Unknown said...

Graeme,

Certainly, having to type in all of the command line options is a pain to do when using the maven archetype plugin. In Maven 1, their used to be an interactive script that would walk you through the process. That capability has been added back in to Maven 2's quickstart archetype. Once you get past the initial set up hurdles, the advantages of Maven far outweigh the disadvantages. I would like to point out that there are some pains to setting up Grails as well. There is still a lot of manual reading that you have to wade through to understand how Grails works. I think that the primary reluctance to work through integrating Maven with Grails is driven by having to learn yet another new framework. That said, I personally think that there is room for both Maven and Grails in one's toolkit.

Anonymous said...

Groovy and Grails are great, but I feel totally disappointed after seeing the horrible directory structure of grails 1.0.4. comparing with maven 2, its build mechanism is a setback, it is the main barrack of our adoption of Grails. I hope grails works with maven 2.

Anonymous said...

"However, once you've copied and pasted your ANT build files for the 10th time, you need to start thinking about re-use and maintenance of these scripts."

No you don't. Every project I've worked on has had an ant script written and then basically forgotten about. With maven, it usually can't even install itself without errors. It's all because of the flawed system of downloading dependencies later rather than with the project. maven's design is flawed.

Anonymous said...

搬家 搬家 搬家公司 搬家 搬家 票貼 借款 徵信社 徵信 補習班 多益 留學 在職進修 婚紗 補正下着 新娘秘書 汽車旅館 室內設計 室內設計 中古車買賣 植牙 坐月子 婚禮佈置 催眠 派報 漆彈 視訊會議 真空成型 Shade sail nike shoes MBA 在职研究生 在职博士 關鍵字廣告 租屋 花蓮民宿 花蓮民宿 花店 花店 花蓮民宿 租房子 xo醬 牛軋糖 牛嘎糖 代償 房屋貸款 信用貸款 失眠 減肥 糖尿病 日立家電 外遇 離婚 抓姦 外遇蒐證 外遇抓姦 侵權 仿冒 應收帳款 工商徵信 徵信 徵信社 外遇 徵信 徵信社 外遇 电动隔膜泵 自吸泵 化工泵 离心泵 磁力泵 螺杆泵 水泵 隔膜泵 气动隔膜泵 白蟻 花蓮民宿 美國留學 新娘秘書 汽車旅館 新娘秘書 催眠 花蓮民宿 搬家 搬家服務 搬家保障 搬家網 搬家估價 徵信 徵信的意義 徵信服務 徵信報導 徵信問答 徵信知識 婚禮佈置 婚禮佈置 http://www.life13.com 票貼 工作服 班服 團體服 糖尿病 勞工體檢 呼吸照護 資源回收 生日禮物 美國遊學 留學代辦 彩妝造型 新娘秘書 宜蘭民宿推薦 催眠 漆彈場 太陽能熱水器 減重 自助洗衣加盟 綠豆椪 床墊 創業加盟 資源回收 鋼戒 廢車回收 創業加盟 龍眼蜜 買房子 買房子 班服配件 團體服配件 團體服 班服 團體服 班服 團體服 眼鏡 創業加盟 室內設計公司 室內設計公司 室內設計公司 最好的婚禮佈置,婚禮佈置花園感官花園婚禮佈置,婚禮佈置最新消息,婚禮佈置專業多元化,為你量身定作完美婚禮佈置,完美的婚禮佈置請來感官花園。婚禮佈置時間雙休請來電預約,婚禮佈置周五正常營業。婚禮佈置地點遼寧街,婚禮佈置聯絡方式電話。婚禮佈置訂購方式,婚禮佈置請提前兩天通知,婚禮佈置請先完成付款及傳真或郵件傳送匯款單。婚禮佈置免費外送價格,婚禮佈置請參考列表。