セルフホストの WCF サービスが InstanceContextMode.PerCall を設定していても並列処理をしてくれない件

セルフホストで WCF のサービスを公開し、外部プログラム(Java)からアクセスしているんですが、 InstanceContextMode.PerCall を設定(呼び出しごとにインスタンスを生成)しても何故か直列で実行されてしまってるぽい。なんでだ?

で、みつけたのが、このスレッドです。

That explains. By default, if there is a synchronization context in the moment the service is started (which is the case for methods called by UI events on WPF/WinForms apps), then WCF will try to deliver all the calls in that same thread (so you can update some UI control within a service call, for example). You can turn this off by setting the [ServiceBehavior(UseSynchronizationContext = false)] in your service.

UIからサービスを起動してる場合、UIスレッドで実行しちゃう。こっちで直列になってしまうってことですね。なので UseSynchronizationContext = false を合わせて設定しなければならない、と。WCF なんて IIS に載っけちゃうことが多いと思うんですが、そうなると気づかないので多くの人はこんなところではハマらないわけで、あんまり情報がありませんでしたが、こんな罠があるとは……。

EntityFrameworkから呼んだストアドのPRINT文の結果を受け取る

コンテキストがctxだとするとこんなので受け取れる。

 var entityConnection = (EntityConnection)ctx.Connection;
 var sqlConnection = (SqlConnection)entityConnection.StoreConnection;
 sqlConnection.InfoMessage += (s, a) => Console.WriteLine(a.Message);

ふむ。SQL Serverでやってるので他のDBはしりません。

WCFでいろいろ悩んでいる件

うーん、要件にうまいこと合致する組み合わせがいまいち分からない。

  • セルフホストでやりたい
  • HTTPSは使わず、HTTPでやりたい
  • カスタム認証を使いたい(イントラ前提で、PC知識があまりないユーザを弾く程度の強度の認証よく、平文がHTTPに乗っても問題ない。独自のユーザ名を使いまわりたいのでWindows認証とかは使えない)
  • クライアントはJava

ってのをやっている。SOAP/WSDLであればJavaとか関係ないだろ、って思うので、問題は上の3つなのですが、認証を載っけようとするとHTTPS必須みたいになってしまうのがどうにも使いにくいですね(しかたないのか)。この要件の中には妥協できる部分もあるんでしょうが、トレードオフもあるわけで、どこを妥協するかが難しいのです。

いちおう抜け道がありそうだなあ。

http://webservices20.blogspot.jp/2008/11/introducing-wcf-clearusernamebinding.html

んー、「SOAP/WSDLであればJavaとか関係ないだろ」とは書いたものの、Axis2側もややこしそうな印象ですね。wsHttpBindingでやると、WS-Securityがかかるので、素のAxis2だと無理で、Rampartを使わないといけない、みたいなことですかね。WCF側はあきらめてHTTPSにしてオレオレ証明書でやっちゃうのはどうかとか思ったけどそれ以前に、ちょっと大袈裟なことをしないといけないわけですかね。JAX-WSはどうなってるの? うーん。そもそもWS-Securityとか今回のケースには大袈裟すぎる気もしなくないんですよねぇ。

というかWS-*シリーズは分からないことが多すぎますね。ネットの記事はけっこう古いものが多くて、最近どうなってるかが完全に抜け落ちてる感じです(まあ枯れつつあるわけですが)。Axis2ではwsHttpBindig繋がりませんよ、なんてコメントもたまにあるんですが、それが2008年だったりすると今は繋がるのか、とかが謎すぎるわけです。さらにライブラリもどれがスタンダードなのかさっぱり分からない。WSS4J とRampertとAxis2とCXFの関係は一体……これはサーバ側で実装する際に使うものなんですかね(ClientとServerで話が混ざっているところもネットでの検索をややこしくしている)

WCFで悩んでいるんじゃなくて、WebServiceで悩んでる感じです。

NuGet 2.5 リリース

ついでに。

NuGet 2.5がリリースされてましたね。リリースノート。ここには書いてないようですが、個人的には「Support for C++ and WiX project types」が目玉です。これまでVS上で、WiXのプロジェクトが含まれているソリューションの全体をNuGetで管理しようとするとエラーが発生し、以後、NuGetのウィンドウを閉じることが出来なくなってしまう現象に悩まされていました。しかたなくWiXプロジェクトはアンロードしていたんですが、アンロードは出来ればしたくないので、これは嬉しい修正です(C++のプロジェクトについては分かりません。ほかにも「Support for Mono/Xamarin projects targeting iOS, Android, and Mac」なんてのもあるようですね)

ほかにもけっこうたくさんのフィーチャが含まれたリリースのようです。

DebugとReleaseでApp.configを切り替える(その3:VS 2012 XDT 編)

なんかフォロー記事ばかり書いてますが、今度はこの記事のフォロー。

このApp.configの切り替え、VS2012で同じことをやってみたんですが、VSが自動修正をいれてくれたのでちょっと訂正をします。前回の記事に

プロジェクトファイル(*.csproj)の

  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />

というタグの下に

  <Import Project="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v10.0\Web\Microsoft.Web.Publishing.targets" />
  <Import Project="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v10.0\WebApplications\Microsoft.WebApplication.targets" />

を追加します

とありますが、この「」の前後を次のようにします。

  <PropertyGroup>
    <VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion>
    <VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
  </PropertyGroup>
  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
  <Import Project="$(VSToolsPath)\Web\Microsoft.Web.Publishing.targets" Condition="'$(VSToolsPath)' != ''" />
  <Import Project="$(VSToolsPath)\WebApplications\Microsoft.WebApplication.targets" Condition="'$(VSToolsPath)' != ''" />

見れば分かりますが、どうも2012でマクロが増えたようで、VisualStudioVersionがとれるようなんですね。でも2010ではとれないのでデフォルト値として設定しておくようです。この記述をすることで2010でも2012でも読めるようになります。

自動更新ライブラリを比較する(その3)

2011年に自動更新ライブラリを比較すると、自動更新ライブラリを比較する(その2)というメモを書いたんですが、その後、結局ライブラリを使うことなく、結局ClickOnceを使いつづけていました。ただ、定期的に他の方法に移行した方が良いんじゃね?熱が再発するのです。なので、今の時点でどうなってるか再チェックだ!

前回取り上げたもの

に加えて、次のをみつけました。

ひとまず、更新日とライセンスをチェック。

ライブラリ バージョン 最終リリース日 最終活動日 ライセンス
NetSparkle 1.0.83 2011.8.10 2012.10.2 MITライセンス
NAppUodate 0.2 2012.6.29 2013.2.13 Apacheライセンス2.0
wyUpdate 2.6.18 2012.8.14 2013.2.13 修正BSDライセンス
DDay.Update 0.72.1 2009.1.2 2012.9.14 BSDライセンス
AutoUpdater.NET 1.2 2013.4.13 2013.4.13 Ms-PLライセンス
dotnetautoupdate 1.0.3543.34728 2009.9.13 2010.10.28 MIT
automatic-updater 2.6.18 2012.8.12 2012.12.23 LGPL

うーん、automatic-updaterとmyUpdateの関係がよく分からんけど、中身は似たようなものなのかなあ。いずれにせよ、下の2つは考慮しなくて良さそうだ。2011年に見つけていた中だと、DDay.Updateももう終わってる感じですが、あとのNetSparkleとNAppUodateとwyUpdateは地味に更新が進んでいて、いきなり更新が止まるってのはなさそうです。新顔のAutoUpdater.NETは、リリースも最近だしチェックしても良いかも。

というわけで、厳選するとこんな感じ。

ライブラリ バージョン 最終リリース日 最終活動日 ライセンス
NetSparkle 1.0.83 2011.8.10 2012.10.2 MITライセンス
NAppUodate 0.2 2012.6.29 2013.2.13 Apacheライセンス2.0
wyUpdate 2.6.18 2012.8.14 2013.2.13 修正BSDライセンス
AutoUpdater.NET 1.2 2013.4.13 2013.4.13 Ms-PLライセンス

とはいえすでにリリースされてるものをClickOnceからの乗り換えるってけっこうハードル高いんですよね。ClickOnceが最初のインストーラも兼ねてくれてるので、更新機能をライブラリでやると、インストーラはつくらないといけない。また、今回もライブラリをチェックしただけでそのままClickOnceで続きそうな気がしなくはない……。

Ubuntu の Redmine をやっと 0.1.3.0 から 0.2.2.1 へバージョンアップした

去年同じような記事を書いたのですが、今年もまたいろいろハマりながらバージョンアップ。個人的にプロジェクトをまたがったチケットの関連をつけたかったのでこのバージョンを待っていたのです。

これまでアーカイブしたファイルを使ってたけどもう、リポジトリ直接取ればいいやと思ったので、SVNから直接取ってきました。

sudo mv redmine redmine_1.3.0
sudo svn co http://svn.redmine.org/redmine/branches/2.2-stable redmine

2.x系から関連ライブラリはBundlerを使うようになったらしいのでBundlerを入れます。

sudo gem install bundler

$REDMINE_HOMEに移動し、Bundlerをつかってライブラリをインストール。

sudo bundle install --without development test

うぐぐ。ImageMagic/RMagicでこけました。よくあるケースです。除外しても良いらしいけどせっかくなのでいれてみた

sudo aptitude install imagemagick libimagemagick libmagickcore libmagickcore-dev libmagickwand-dev
sudo gem install rmagick -v 2.13.1

さあ、うまくインストールできた。

files以下をコピーして、マイグレーションをかける。その他いろいろrakeをせよという指示があるのでまとめて。

rake generate_secret_token
rake db:migrate RAILS_ENV=production 
rake redmine:plugins:migrate RAILS_ENV=production 
rake tmp:cache:clear
rake tmp:sessions:clear


ところが、いろいろライブラリが足りないと言われる、えーBundlerで入ったんじゃないのかよ。しかたないのでエラーが出る度にgemでインストールを繰り返し(すいません、メモするのわすれたのですが、基本的にgemで全部行けました)

終わったので、さっそくapache2を再起動(Apache2+Passengerでうごかしてます)したところ、なぜか404に。ファイルを置くと見えるので、Railsの中で404がでているのだろうけどどこかわからない。Apacheはエラーはいてないし……。Railsが新しくなったからPassengerの設定が変わったのかと思って、passenger.confを見たりいろいろしたのだがまったく状況に変化がない。これがひどく時間を食ってしまった。最終的にlog/passenger.logにRailsのエラーログが出てることに気づいた。どうもプラグインの1つ(work_timeプラグイン)が1.x系のものだったのが良くなかったようで、これを2.x系のものに差し替えたら動きました。

ふー、一日使ってしまった。