SMBCと地銀の両方申し込んだけど、地銀の方は申し込みの翌日連絡があり口座開設OKなのでまた来てくださいとの事。SMBCの方は10日くらいたった後に、法人名義の公共料金領収書か不動産登記が必要との事。作ったばっかりだし、領収書なんてすぐできないでしょ?とりあえず地銀の口座が開設出来たので、都市銀の方は暫く放置かな?べつに無くても困らないし。。
投稿者「bokusui」のアーカイブ
DMの嵐
法人登記後、本店の住所に次から次へとDMが届いてました。普通の家なんで、この会社はこの住所で合ってますか?と配達員が怪しんでいたみたいです。こういう場合、表札に会社名を付けとかないとメンドクサイですね。
で、DMですが、主に地元の税理士事務所が殆どですが、社会保険労務士事務所と任意労災保険とか。。
「法人なり」なんで、既に個人事業主としての青色申告は何回もやっているのですが、法人の場合はどう違うのかいまいち解ってません。税務関係は別途調べるとしてしばらく放置です。
今日は地元の地銀に法人口座の申し込みをしにいきましたが、1週間で返事しますとの事。すぐに口座開設できないのは、都市銀だけじゃないのですな。。
法人登記してみた
仕事の関係で、個人事業主より法人化すべきと思い、、してみました。
基本的には、
に書いてあるまま文書を作って自力で手続きをしましたが、あまり経験する事もないのでメモっときます。基本的に平日時間が取れるので全て「オフライン」申請でしました。
定款認証については、定款を一通り書いた後に管轄の公証役場に電話したところ、事前に内容をチェックしますのでFAXで送って下さいとの事で、FAXで送った翌日に指摘事項がFAXで返送されてきたのでそれを定款に反映し、再FAXするといったやり取りがありました。最初の電話から数日後、実際に定款をプリンタで印刷、個人の実印で捺印したものを3部と実印、印鑑証明を用意して公証役場へ持っていき認証を行いました。事前に送ってチェックしてもらっていたので、係員の人が定款書類をホチキス止めして30分もせずに済みましたが、印紙代4万と手数料5万+αってちょっと高くないですか??
定款認証後は、社印を購入して法務局への登記申請に進みます。申請書等も上記リンクそのままで文書を作成して法務局に持っていきました。こちらも収入印紙を15万購入後にあっけなく終了。受付窓口でパラパラと書類をチェックした後に「何かありましたら連絡します」と紙を渡され、それには9日後が登記完了予定日となってます。
数日後、法務局から電話連絡がありました。登記事項の確認との事で、株の発行をしない場合は、株券を発行する旨を記載しなくてよいとか、一人でも代表取締役は登記に記載が必要なので、取締役をそのまま載せますとか。。登記申請時にテキストファイルで定款の要約的な内容を書いたCD-ROMを持って行っているんですが、この内容を確認しているようです。
で、完了の日が来たので、また法務局へ行って登記事項証明書と印鑑カードを取得、これで一応法人が出来たという事みたいです。なお、登記事項証明書は正確には「履歴事項全部証明書」と解りにくい名前です。これを見ると、CD-ROMの内容がそのまま登記されている事が解ります。設立日は想定通り登記手続きをしに行った日になりました。
税務署とか後日行ってきます。
WLSのデータソース設定せずにJPA
今筆者が作っているWEBアプリケーションのDB周り実装です。
インフラ的には、主にWLS12+OracleDBとなっていますが、社内特定部署に利用が限定されたアプリケーションなので、DBセッションは「節約したい」という微妙な要件です。さらに、WLSデータソース設定はしたくないとの希望です。
せっかくEE使うんで、JPA前提でやる事にしますが、WEBに出てる殆どのネタがWLSのデータソースを使っているんですよね。
セッションプールは別途OracleUCPの独自実装があるので、persistance.xmlで指定せずに、UCPのデータソースをプログラム上からエンティティマネージャに指定するというイメージなんですが、WEBで調べながら実際に動くまで結構時間掛かりました。。
まず、EclipseのプロジェクトファセットにJPAを追加するとpersistence.xmlが出来ますが、データソースをここでは設定しないのでエンティティクラス定義のみ書きます。
1 2 3 4 5 6 7 8 |
<?xml version="1.0" encoding="UTF-8"?> <persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"> <persistence-unit name="DBresource" transaction-type="RESOURCE_LOCAL"> <class>jp.xxx.zzz.model.user.LoginUser</class> 他クラス定義省略 <exclude-unlisted-classes>true</exclude-unlisted-classes> </persistence-unit> </persistence> |
次にエンティティクラス(テーブル定義みたいなもの)
1 2 3 4 5 6 7 8 9 10 11 12 13 |
@Table(name="USER_MST") @Entity public class LoginUser implements Serializable{ private static final long serialVersionUID = 1L; /** ユーザーID*/ @Id @NotNull @Size(max=20,min=7) private String USER_ID; /** ユーザーパスワード*/ private String USER_PASS; /** ユーザー種別*/ @NotNull private String USER_TYPE; 以下、項目とゲッタセッタは省略 |
その次が、データアクセスインターフェース(データ操作定義)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
/** * ログインユーザーマスタ * Data access object interface * */ public interface LoginUserDao { /*** * データ1件取得 * @return キー * */ public LoginUser find(Object id); /*** * データ新規作成 * */ public void create(LoginUser entitiy); /** * データ更新 * */ public void update(LoginUser entitiy); /** * データ全件取得 * */ public List<LoginUser> getAll(); /** * データ件数取得 * */ public long getAllCnt(); } |
さらに上記インターフェースをJPA実装したデータアクセスオブジェクト(DAO)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 |
/** * ログインユーザーマスタ * Data access object (JPA) * */ @Stateless //@TransactionAttribute(TransactionAttributeType.REQUIRED) public class LoginUserDaoJpa implements LoginUserDao{ protected static Logger logger = LogManager.getLogger(); public EntityManager em = null; /** * コンストラクタ * */ public LoginUserDaoJpa() { super(); em = DBEntityManager.getEntityManager(); } /** * データ検索 * @param id (key) * @return LoginUser * */ @Override public LoginUser find(Object id) { return em.find(LoginUser.class, id); } /** * データ新規登録 * @param ServerConf * */ @Override public void create(LoginUser entity) { EntityTransaction txn = em.getTransaction(); txn.begin(); if ( ! em.getTransaction().isActive() ){ em.getTransaction().begin(); } em.persist(entity); txn.commit(); } /** * ユーザーマスタの全取得 * @return ログインユーザーマスタのリスト * */ @SuppressWarnings("unchecked") @Override public List<LoginUser> getAll() { //後日追加 em.clear(); List<LoginUser> result = em.createQuery("SELECT c FROM LoginUser c WHERE c.STATUS_FLG < :SFLG ORDER BY c.USER_ID") .setParameter("SFLG", "9") .getResultList(); return result; } /** * ユーザーマスタより業務メンバーの取得 * @return ログインユーザーマスタのリスト * */ @SuppressWarnings("unchecked") public List<LoginUser> getBizMember() { //後日追加 em.clear(); List<LoginUser> result = em.createQuery("SELECT c FROM LoginUser c WHERE c.USER_TYPE < '5' AND c.STATUS_FLG < :SFLG ORDER BY c.USER_ID") .setParameter("SFLG", "9") .getResultList(); return result; } /** * データ更新 * @param ServerConf * */ @Override public void update(LoginUser entity) { EntityTransaction txn = em.getTransaction(); txn.begin(); if ( ! em.getTransaction().isActive() ){ em.getTransaction().begin(); } em.merge(entity); txn.commit(); } /** * 件数取得 * */ public long getAllCnt() { return em.createQuery("SELECT c FROM UserMaster c").getMaxResults(); } } |
上記DAOのコンストラクタで読んでいるEntityManagerを取得するシングルトンクラス
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
public class DBEntityManager { protected static Logger logger = LogManager.getLogger(); private static Map<String, Object> configOverrides; static { Map<String, Object> map = new HashMap<String, Object>(); try { //ここのDBConnectionMgrとは、UCPを使用してデータソースを戻す独自実装です・・ //独自実装内で各種JDBC設定がされています・・ map.put("javax.persistence.nonJtaDataSource", DBConnectionMgr.getDataSource()); } catch (SQLException e) { logger.error("DBConnectionPool JpaEntityManager put Error!", e); } configOverrides = Collections.unmodifiableMap(map); } /** * EntityManagerを返します * */ public static EntityManager getEntityManager(){ return Persistence.createEntityManagerFactory("DBresource", configOverrides).createEntityManager(); } } |
上記を呼び出しているJava画面ソース
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
/** * ユーザーマスタ管理画面処理(ユーザー作成・更新・削除・パスワード変更共通) * * */ @ManagedBean(name="UserManager") @ViewScoped public class UserManager implements Serializable { private static final long serialVersionUID = 1L; @EJB private LoginUserDao dao; List<LoginUser> List; @ManagedProperty("#{userDto}") LoginUserDto user; public LoginUserDto getUser() { return user; } public void setUser(LoginUserDto user) { this.user = user; } /** 以下画面項目 */ public List<LoginUser> getList() { List = dao.getAll(); return List; } public void setList(List<LoginUser> list) { List = list; } 以下省略 |
最後に上記呼び出し箇所のXHMLの抜粋
1 2 3 4 5 6 |
<h:dataTable var="item" value="#{UserManager.list}" columnClasses="userid,username" > <h:column> <f:facet name="header">#{words.Label_UserID}</f:facet> <h:outputText value="#{item.USER_ID}" /> </h:column> </h:dataTable> |
後で、テストしたところ、DB更新は出来ていてもクエリーでデータを取得すると反映していませんでした。永続化コンテキストからみの事象と思われますが、細かい仕様を調査するのは骨が折れるので、、、クエリー取得前にEntityManagerをclearする事で対処としました。
VBSでFTP
あるWindowsサーバのログファイルを別サーバへ定期的にFTP送信したいとの事で、VBSで簡単なスクリプトを作りました。これまでは、バッチやスクリプトでFTP用のコマンドファイルを作り、FTP -S:ファイル名で実行するような感じだったのですが、最近は、スクリプトだけでできるようです。
下記例は、D:\log\tempというディレクトリに一つのzipファイルが置かれており、そのファイルを送信するという前提です。
ちなみにzipファイル自体の名前でstrSrcを指定するとCopyHereが勝手にZipの中身を解凍した状態で送信されます。。そういや、CopyHereでzipの圧縮や解凍もできるからそういう事なんでしょうか。。恐るべしCopyHere
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
'FTP送信指定 Const HostName = "192.168.1.101" Const UserID = "userid" Const UserPass = "password" Const DestDir ="Upload" Dim strDest,strSrc, UpFileName, UpFileSize, oSH, objDest strSrc="D:\log\temp" strDest = "ftp://" & UserID & ":" & UserPass & "@" & HostName & "/" & DestDir Set oSH = CreateObject("Shell.Application") Set objDest = oSH.NameSpace(strDest) WScript.Echo "[" & strSrc & "]FTP転送対象" For Each objItem In oSH.NameSpace(strSrc).Items WScript.Echo "[" & strSrc & "]FTP転送ファイル [" & objItem.Name & "]," & objItem.Size UpFileName = objItem.Name UpFileSize = objItem.Size '&H04 + &H10は効かない・・・ objDest.CopyHere objItem, &H04 + &H10 Next '非同期なのでスリープで待つ・・・ Wscript.Sleep 15000 'リモートディレクトリの送信ファイル存在確認 Dim CheckOK, iWaitCnt CheckOK = False For iWaitCnt = 0 To 10 Set objDest = oSH.NameSpace(strDest) For Each objItems In objDest.Items If UpFileName = objItems.Name Then 'リモートファイルのサイズは取れないみたい・・・ WScript.Echo "[" & strSrc & "]FTP転送ファイル確認 [" & objItems.Name & "]," & objItems.Size CheckOK = True Exit For End If Next If CheckOK = True Then Exit For End If Wscript.Sleep 10000 WScript.Echo "FTP転送待ち[" & iWaitCnt & "]" Next If CheckOK = False Then WScript.Echo "FTP転送に失敗しました " & Err.Number Else WScript.Echo "FTP転送正常終了" End If |
でも、このCopyHere、FTPでは非同期のようで送信終了タイミングが解らなくスリープ待ちせざるを得なかったり、上書き確認のダイアログがどうしても消せない等、ちょっとクセが強いです。。
今回の要件的にはまあ上書きの対処は見切りました。確実性が必要な処理だとこのやり方はしないかな~
要件定義書というシロモノについて
システムを作る際に、要件定義として何かしらドキュメントを書きますが様々なタイプがありますよね?
筆者が社内SEやってたときは、メイン読者は誰なのかを特に意識して書いてきました。それによってドキュメントの目的が違ってくるからです。それに読む人が理解できないものを書いてもしょうがないじゃないですか?
よく見かける「要件定義書」を成果物と設定し、ドキュメントそのものが目的物になっている場合って、何かピンとこないことが多いように思うんですが、ドキュメントって全ての読者向けに書いた、もしくはターゲットを特定しない場合は、ページ数が多くて読む気もならなかったり、ちょっとの誤字脱字を発見して読む気なくしたりして、誰にも伝わらない、もしくは各自の思いで解釈し後で痛い目にあうというなんて事も多々あるように思います。
という事でメイン読者を軸にすると主に4タイプに分類できるかなと思います。
1.経営者向け
あまり書く機会は無かったけど、この場合の目的はビジネスがどう変わるか、予算がどのくらいかかりそうかが焦点かと。
とにかく簡潔に少ないページ数でまとめる。図を多く使ってパワポで書く。
2.利用者(利用部門)向け
この場合の目的は、業務がどう変わるか、システム化される範囲としない範囲の指定なんで、具体的な対象物の明記が必要。
概要説明と解りやすそうな業務フロー(UML的に書いても理解されない可能性が高いです)
また、外部設計を後でやるかやらないかにもよりますが、画面・帳票設計に近いもの付け加える。
3.開発者向け
開発工数を見積もるという目的がメインと考えます。
どういうレベルの工数見積もりを期待するかで、たくさん書くこともあれば、ちょっとの時もあり・・
開発者の理解レベル次第では、2と同じにする事も多々あり・・
4.運用管理者向け
この場合の目的は、どう構築して、その後維持管理していくかなんで上記とは別物ですね。いわゆる非機能要件に分類される内容がメインになると思われます。
現在の筆者のスタンスでは、自分では要件定義書的なものを書きません。
だって見積もりもしなければ、別の開発者に伝える必要もほとんどないし・・・
開発者という立場の場合、見積もりしない限り、手間が掛かるだけで必要性を見いだせないからです。
よく開発ベンダーに要件定義書を任せるというスタンスの所もあります。開発規模次第という面もありますが、出来ればしない方がいいですね。あれもこれもといろいろ盛られて、見積もり見てびっくりします。
JAX-RSを使ってみる
今筆者が作っているサブシステムは、複数種類の定期ジョブとWeblogicで動作させる画面アプリと組合せなんですが、定期ジョブの実装方式として、JAX-RSを検討しました。
なんでジョブをJAX-RSで作るのか?という所なんですが、Weblogicデプロイモジュールに含めることでジョブ実行時のメモリ消費をインフラ設計範囲内に収める為(Coherenceキャッシュへのアクセスがある)と、ジョブ変更時のモジュール管理をサブシステムとして統一したいという理由です。
あと、ジョブ起動については既存のジョブ管理ツールに統一したいとの事なので、EJBスケジューリングは使えない前提です。というか、EJBスケジューリングの挙動検証がしきれてないので、お勧めするのを躊躇したという所なんですが。。
当然、そのままだと外部からアクセスできるので、セキュリティ対策としては要求元IPでフィルタする形で対応する事としてます。
簡単な汎用POSTリクエストモジュールを作成した後、JAX-RSとして動作する処理をJavaEEアプリ内に作成します。
Weblogicデフォルトではなぜか動かなかったので、
weblogic.jaxrs.server.portable.servlet.ServletContainerを使わず、
POMにjerseyを追加
1 2 3 4 5 |
<dependency> <groupId>com.sun.jersey</groupId> <artifactId>jersey-core</artifactId> <version>1.19</version> </dependency> |
web.xmlを上記に合わせる
1 2 3 4 5 6 7 8 9 10 |
<servlet> <description>JAX-RS Tools Generated - Do not modify</description> <servlet-name>JAX-RS Servlet</servlet-name> <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>JAX-RS Servlet</servlet-name> <url-pattern>/batch/*</url-pattern> </servlet-mapping> |
JAX-RSソース(コンテキストルート/batch/JOB1のURLでPOST実行)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
/** * バッチ処理 * */ @Path("/JOB1") public class BatchExecute{ public String hello(@Context HttpServletRequest request) throws InterruptedException { return "Batch GET Hello!"; } /** * ジョブ実行 * */ @POST public Response execute(@Context HttpServletRequest request) { //POSTパラメータ取得 String Interval = request.getParameter("PARAM1"); ・・・以下省略 } } |
ジョブ管理の側はログファイルの検知をトリガーにするので、どのプロセスがログに書いたかはどうでもよく、これで行こうと思います
追伸 1年経って下記のような事もありました。。
weblogic.xmlのprefer-web-inf-classesをtrueにしたらハマった・・