'분류 전체보기'에 해당되는 글 2491건

  1. 2014.04.23 jqGrid 簡単サンプル
  2. 2014.04.22 jqgrid drag & drop 1
  3. 2014.04.11 How to configure distributed transaction in Oracle Database Gateway for ODBC? (ORA-02047)
  4. 2014.04.11 [펌] ORA-02047: cannot join the distributed transaction in progress 1
  5. 2014.04.07 eclipse 3.4 이전버전들 jrabel updata 주소
  6. 2014.04.02 scala api
  7. 2014.04.02 하이브리드앱 원격 디버깅
  8. 2014.04.01 [펌] 모바일 원격 디버깅 Weinre
  9. 2014.04.01 JSONP
  10. 2014.04.01 [펌] [Tip] JSONP를 이용하여 Cross Domain 해결
  11. 2014.04.01 jQuery.ajax() HTTP 비동기 데이터 교환
  12. 2014.03.28 Scala - How to open and read files in Scala
  13. 2014.03.28 How to load an XML URL in Scala (contents of an XML web page)
  14. 2014.03.28 How to load (open and read) an XML file in Scala
  15. 2014.03.28 Scala: Saving/writing XML to a file
  16. 2014.03.28 How to mix Scala and XML to dynamically generate XML
  17. 2014.03.28 A Scala REST client using the Apache HttpClient library
  18. 2014.03.28 A Scala JDBC connection and SQL SELECT example
  19. 2014.03.28 Scala tuple examples and syntax
  20. 2014.03.28 Iterating over Scala Maps (for and foreach loop examples)
  21. 2014.03.28 Scala Maps (Map class examples)
  22. 2014.03.28 Scala List class filter method examples
  23. 2014.03.28 Scala List class examples - range, fill, tabulate, appending, foreach, more ...
  24. 2014.03.28 Five ways to create a Scala List
  25. 2014.03.28 How to merge Scala Lists
  26. 2014.03.28 Iterating over Scala Lists with foreach and for
  27. 2014.03.28 Convert a Scala array to string with mkString
  28. 2014.03.28 Iterating over Scala Maps (for and foreach loop examples)
  29. 2014.03.28 Iterating over Scala Lists with foreach and for
  30. 2014.03.28 How to create and use multi-dimensional arrays (2D, 3D, etc.) in Scala
반응형


今回は昨年末(2011/12/20)にリリースされたjqGrid4.3.1の新機能を実際に使ってみましょう。
#というのも、実際使おうとしたらVersion.4台でサンプルプログラム載せている
 ところがほとんどなかったので私にとっての備忘録です。
 今回は最終成果物(DLすればすぐ動かせるもの)もこのページに掲載します。

今回試すのは以下の機能です。

  • 行/列のセルマー(ColSpanとかRowSpanとかいうアレ)
  • スクロール時のセル固定(Excelで見かけるアレ)

ん〜、にしてもどんどんExcelと同じようなことができるようになってきてますね。
便利になるのはいいとしても、パフォーマンス大丈夫なのかな?
大量データを描画する際に間違いなくパフォーマンス問題を起こしそうな。。。

まぁ、今回はそこには触れずに上記新機能を実装します。

完成イメージ

今回は先に結論と成果物を共有しちゃいます。
jgGrid_sample.zip 直
これをDLしてsample.htmlを開くと、こんな画面が開けます。

スクロールすると、こんな感じにセル固定もします。

ちなみに、これら、デモサイトの作りと異なる作りをしています。
つまり、、、デモサイトの情報はこれから紹介する問題に対応していないんです!!!
古い!!!
早期改修を期待します。

内容解説

Group Header

まずはセルマージのアレを実現します。
これはjQueryメソッド内で以下を呼んであげれば実現完了です。

$("#sample1").jqGrid('setGroupHeaders', {
	useColSpanStyle: true,
	groupHeaders:[
		{startColumnName: 'age', numberOfColumns: 3, titleText: '<em>Details</em>'},
		{startColumnName: 'note1', numberOfColumns: 3, titleText: '<em>Notes</em>'}
	]
});

「useColSpanStyle: true」という指定で縦セル結合の設定。
groupHeadersで横セルのマージを行っています。
なんと簡単なことか!

Frozen Cols

次にセル固定についてです。jqGrid4.3.0から、何と1つの設定とメソッド呼び出しで
機能として実現されます。
#まずはデモサイト通りの実装です。
colModelの設定で以下を設定します。

frozen:true
/** 例:{name:'name',index:'name',width:150,align:'center',classes:'name_class',frozen:true}, */

次に、jQueryの最後で以下のメソッドを呼び出します。

$("#sample1").jqGrid('setFrozenColumns');
/** #sample1はサンプルのテーブルID */

これだけで実装完了です。これも簡単!

ハマりどころ

[Frozen Cols]そもそもテーブル操作しないとセル固定が中途半端に実現される

上記のとおりjQuery内で最後にメソッド呼び出しをすると、、、こうなります。
Windows 7 64-bit環境)

忌々しき事態です、まったく使い物になりません。

ちなみにテーブル操作を行って一度でもテーブルをリフレッシュさせると問題は起こりません。。。

色々調べましたが、全く同じ症状の人がいましたね。掲示板にて外人さんが質問しています。
英語のフォーラムなのであまり読んでませんが要約するとこんな感じでしょうか。

ユーザ
そのままsetFrozenColumnsメソッド使ってもうまく固定されないから
リロードする仕組み入れてるんだけど、リロードってパフォーマンス落ちるよね?
何とかならないの?
製作者
こっちじゃ確認できないよ、環境悪いんでない?

・・・(こんなやり取りを何度か繰り返す。)

製作者
確かに問題がありそうだね、こちらでも確認したよ。
ユーザ
現状はこうやって解消してますわぁ。

gridComplete: function() {
mygrid.jqGrid('setFrozenColumns');
}

なるほど、colModelの属性としてgridCompleteに設定するのね。
これならgrid完成後にセル固定処理が走るから問題なさそうですね。
これで一つ解決

[Frozen Cols]セル固定状態のフィルタリングで処理がストップする

上記gridCompleteに記述することにすると、次にこの問題にあたります。
セル固定やマージは一度だけ行えばいいのに、gridComplete内に記述すると、
フィルタなどの再描画の際にもさらにマージしようとするから生じるのかな?

いずれにしても、処理がストップしてフィルタリングができません。
一応現在は下記のようにして回避しています。

var isLoaded = false;

・・・

gridComplete: function(){
  if (!isLoaded == true){
    $("#sample1").jqGrid('setGroupHeaders', {
      useColSpanStyle: true,
      groupHeaders:[
        {startColumnName: 'age', numberOfColumns: 3, titleText: '<em>Details</em>'},
        {startColumnName: 'note1', numberOfColumns: 3, titleText: '<em>Notes</em>'}
      ]
    });
    $("#sample1").jqGrid('setFrozenColumns');
    isLoaded = true;
  }
},

一度でもセルマージなどの読み込みを行ったら、その後は行わない、という実装です。
一応今のところこれで問題が発生しなくなっています。
(他の機能との連携を全て試しているわけではないのでどうなるかわかりませんが。。。)

いずれにしても、本体の改修でこの辺の問題がFixされることを期待しています。
jqGridは最近とても短い期間でBugFix版を出しているので、
(4.3.0から4.3.1へのUpdateも10日足らず)すぐに修正されることを願っています。

では、今回はこの辺で。


Posted by 1010
반응형
http://stackoverflow.com/q/12606945/315935
jqgridDnD.html
Posted by 1010
02.Oracle/DataBase2014. 4. 11. 16:40
반응형

I am connecting from Oracle to MS SQL Server through an ODBC connection using Oracle SQL Developer. (How)

I want to query the schema of the MS SQL database using the data dictionary mapping of the Oracle Database Gateway for ODBC.

This works well:

select * from all_tables@katimssql;

But this doesn't:

create table alltables_mssql as 
select * from all_tables@katimssql;

Output:

Error report:
SQL Error: ORA-00604: error occurred at recursive SQL level 1
ORA-02047: cannot join the distributed transaction in progress
ORA-06512: at "SYS.HS$_DDTF_SQLTABLES", line 58
ORA-06512: at line 1

Does anyone know the solution of this?
Thanks in advance,
Kati


 

Details:

Oracle Database 11g Express Edition Release 11.2.0.2.0
Microsoft SQL Server 2008 (SP2) - 10.0.4000.0 (X64)
ODBC Driver: SQL Server Native Client 11.0 (32 bit)

initkatimssql.ora:

HS_FDS_CONNECT_INFO=katimssql
HS_FDS_TRACE_LEVEL = ON
HS_TRANSACTION_MODEL = READ_ONLY_AUTOCOMMIT

I tried these, none of them worked, the error message is the same.

HS_FDS_TRACE_LEVEL = off
HS_TRANSACTION_MODEL = SINGLE_SITE
HS_TRANSACTION_MODEL = READ_ONLY_AUTOCOMMIT
HS_TRANSACTION_MODEL = READ_ONLY
Posted by 1010
02.Oracle/DataBase2014. 4. 11. 16:32
반응형

ora-02047: cannot join the distributed transaction in progress
Cause: Either a transaction is in progress against a remote database that does not fully support two phase commit, and an update is attempted on another database, or updates are pending and and an attempt is made to update a different database that does not fully support two phase commit.
Action: complete the current transaction and then resubmit the update request

출처 : http://dpldpl.tistory.com/7

ORA-02047 동작중의 분산 트랜잭션(transaction)는 결합할 수 없습니다.

 

원인은 이기종 데이터베이스 시스템 간의 인터페이스 작업 시(ex. oracle to mssql)

데이터 처리를 함에 있어서(ex. Insert, Update, Delete)

커밋을 하지 않았기 때문에 발생하는 오류이다.

 

단일 시스템에서는 커밋을 하지 않아도 무방하지만

이기종 시스템간의 데이터 처리시에는 DML 구문뒤에 꼭 커밋을 해주어야 한다.

 

by. 덕평물류 전산정보팀(DPL Dream Partner in Logitics)

Posted by 1010
98..Etc2014. 4. 7. 13:43
반응형

http://update.zeroturnaround.com/update-site-archive/

Posted by 1010
00.scala2014. 4. 2. 00:58
반응형

http://www.scala-lang.org/api/current/#package

http://www.slideshare.net/choijeongyeol/scala-for-play

scala cheatsheets

http://docs.scala-lang.org/cheatsheets/


스칼라를 배울 수 있는 사이트

스칼라 서적(영문)

  • Programming in Scala : 마틴 오더스키가 참여한 스칼라 서적. 강추!!, Scala 2.8 기준.
  • Programming Scala : 오렐리에서 나옴. 읽어본 사람 없어서 내용은 잘 모름.
  • Programming Scala : Pragmatic에서 나온 스칼라 서적. 읽어볼만은 하지만 빠진 내용이 많아서 많이 추천하지는 않음.
  • Scala in Depth : 매닝에서 나온 서적. 읽어본 사람이 없어서 내용은 잘 모름.

그외 참고 자료

발표자료

슬라이드


Posted by 1010
98..Etc2014. 4. 2. 00:35
반응형

http://hanho9.cafe24.com 나오는 2번에 스크립트 경로를 아래에 스크립트에 적용후 


javascript:(function(e){e.setAttribute("src","http://debug-software.intel.com/target/target-script-min.js#anonymous");document.getElementsByTagName("head")[0].appendChild(e);})(document.createElement("script"));void(0);


실제 디버깅할 곳에 삽입

------------------------------------------



http://debug-software.intel.com/

http://debug.phonegap.com/



Tutorial-UsingDebugMobi.pdf




 

 

 

 

 

 

 

 

 

 

 

 

Intel® HTML5 Development Environment 

Tutorial – Using App Debugger 

v1.05 : 03.06.2013 Tutorial – Using App Debugger v1.05 : 03.06.2013 

 

 

Legal Information 

INFORMATION IN THIS DOCUMENT IS PROVIDED IN CONNECTION WITH INTEL PRODUCTS. NO LICENSE, 

EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, TO ANY INTELLECTUAL PROPERTY RIGHTS IS 

GRANTED BY THIS DOCUMENT. EXCEPT AS PROVIDED IN INTEL'S TERMS AND CONDITIONS OF SALE FOR 

SUCH PRODUCTS, INTEL ASSUMES NO LIABILITY WHATSOEVER AND INTEL DISCLAIMS ANY EXPRESS OR 

IMPLIED WARRANTY, RELATING TO SALE AND/OR USE OF INTEL PRODUCTS INCLUDING LIABILITY OR 

WARRANTIES RELATING TO FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABILITY, OR 

INFRINGEMENT OF ANY PATENT, COPYRIGHT OR OTHER INTELLECTUAL PROPERTY RIGHT. 

A "Mission Critical Application" is any application in which failure of the Intel Product could result, 

directly or indirectly, in personal injury or death. SHOULD YOU PURCHASE OR USE INTEL'S PRODUCTS 

FOR ANY SUCH MISSION CRITICAL APPLICATION, YOU SHALL INDEMNIFY AND HOLD INTEL AND ITS 

SUBSIDIARIES, SUBCONTRACTORS AND AFFILIATES, AND THE DIRECTORS, OFFICERS, AND EMPLOYEES 

OF EACH, HARMLESS AGAINST ALL CLAIMS COSTS, DAMAGES, AND EXPENSES AND REASONABLE 

ATTORNEYS' FEES ARISING OUT OF, DIRECTLY OR INDIRECTLY, ANY CLAIM OF PRODUCT LIABILITY, 

PERSONAL INJURY, OR DEATH ARISING IN ANY WAY OUT OF SUCH MISSION CRITICAL APPLICATION, 

WHETHER OR NOT INTEL OR ITS SUBCONTRACTOR WAS NEGLIGENT IN THE DESIGN, MANUFACTURE, OR 

WARNING OF THE INTEL PRODUCT OR ANY OF ITS PARTS. 

Intel may make changes to specifications and product descriptions at any time, without notice. 

Designers must not rely on the absence or characteristics of any features or instructions marked 

"reserved" or "undefined". Intel reserves these for future definition and shall have no responsibility 

whatsoever for conflicts or incompatibilities arising from future changes to them. The information here 

is subject to change without notice. Do not finalize a design with this information. 

The products described in this document may contain design defects or errors known as errata which 

may cause the product to deviate from published specifications. Current characterized errata are 

available on request. Contact your local Intel sales office or your distributor to obtain the latest 

specifications and before placing your product order. Copies of documents which have an order number 

and are referenced in this document, or other Intel literature, may be obtained by calling 1-800-548-

4725, or go to: http://www.intel.com/design/literature.htm 

Intel and the Intel logo are trademarks of Intel Corporation in the U.S. and/or other countries. 

*Other names and brands may be claimed as the property of others. 

Microsoft, Windows, and the Windows logo are trademarks, or registered trademarks of Microsoft 

Corporation in the United States and/or other countries. 

Copyright © 2013, Intel Corporation. All rights reserved. Tutorial – Using App Debugger v1.05 : 03.06.2013 

 

 

1.0 Purpose 

The purpose of this documentation is to demonstrate how to use the App Debugger tool to remotely 

debug HTML5 code over the Internet. The App Debugger tool is based on an open source tool called 

“Web Inspector Remote”* (WEINRE) that provides remote Web debugging for mobile devices. 

However, App Debugger is a configuration-free hosted version of that software that anyone can use for 

free across the Internet. 

2.0 How to Use App Debugger 

To use the App Debugger tool, browse to http://debug-software.intel.com in your Google* Chrome web 

browser. 

 

A unique identifier is generated automatically for you. If you were returning to App Debugger after 

debugging previously, you might instead enter your current unique ID. 

Once you have determined the unique id that will be used for the current debugging session, make sure 

that your HTML5 project has the listed script included in it. It could go anywhere, but for consistency it 

is typically placed just after the closing body tag in your HTML document. 

 

<html><body></body> 

<script src="http://debug.html5m.com/target/target-script-min.js#ac4928aa-418b-d4c8-

5839-1a6b278c0146"></script></html> 

 

 

Next, click the link to start App Debugger on your Chrome* browser. That will bring up a remote page 

that looks something like this: Tutorial – Using App Debugger v1.05 : 03.06.2013 

 

 

 

There are no targets yet. Once the JavaScript* library is loaded into an HTML5 page, that page will show 

up as one of the available targets in just a few seconds. 

 Tutorial – Using App Debugger v1.05 : 03.06.2013 

 

 

Once the target has fetched the WEINRE JavaScript from the server, executed it, and made a good 

contact back to the App Debugger server, the Target will turn green. 

 

If you have several Targets, select the one you want to view. You should then be able to use Chrome’s 

debugging tools similar to how one would use those tools to debug local JavaScript. Switch to the 

Console view within Chrome to see the console.log messages coming from the remote JavaScript. 

 Tutorial – Using App Debugger v1.05 : 03.06.2013 

 

 

3.0 Finding Bugs 

The App Debugger tool can help you to find bugs in your remote JavaScript/HTML code in several ways. 

3.1 Capture console.log calls 

Any JavaScript messages logged to the console using console.log will make their way to the App 

Debugger console window. That can save you the heartache of having to write messages to the screen 

as a debug log or putting up a load of annoying alert boxes. In the example below, the HTML5 program 

running on the right is transmitting its console.log calls to the App Debugger window on the left. 

 

 

3.2 Adjust CSS on the Fly 

The App Debugger window also gives you the ability to change CSS elements and immediately see the 

results on the client side. In the example below, the CSS for the title page is adjusted and the result 

plays out immediately on the client window to the right. Tutorial – Using App Debugger v1.05 : 03.06.2013 

 

 

 

3.3 Adjust JavaScript on the fly 

The App Debugger window gives you the ability to write JavaScript and have it executed immediately on 

the client side. In the example below, the canvas tag which includes the kung-fu fighter is set to be 

transparent, making him appear ghostly in the right window. 

 Tutorial – Using App Debugger v1.05 : 03.06.2013 

 

 

3.4 Inspect HTML 

The App Debugger tool allows you to inspect HTML elements. Highlighting the HTML code in the App 

Debugger window will highlight the element on the client side. In the example below, the HTML 

element for the title is selected for inspection which highlights it in the right-hand execution window. 

 

4.0 More Information 

For more information, check out a quick demonstration video here: 

http://youtu.be/k0t2oZKpmA8 

The App Debugger service is also available as a Chrome extension here: 

http://tinyurl.com/debugmobi-chrome 

For a more detailed explanation of how WEINRE works link here: 

http://muellerware.org/papers/weinre/manual.html 

 

 

Posted by 1010
98..Etc2014. 4. 1. 18:20
반응형

Weinre(와이너 or 와이너리)란?

  server는 java기반의 http서버 (jetty)

  client는  webkit계열의 브라우저 (일반적으로 서버와 같은 pc에서 실행)

  target은 webkit계열의 브라우저 (일반적으로 태블릿, 폰의 브라우저)

  위와같이 구성된 디버깅 라이브러리이고 태블릿과같이 javascript디버깅을 할수없는 기기에서 

  target(태블릿) => server(pc)로 http통신을 하여 client(pc의 브라우저)로 원격 디버깅을 할 수 있습니다.

  참고로 2.0버전부터는 Weinre의 서버가 node.js로 변경 되었습니다만

  여기에서는 java기반 서버의 마지막 버전인 1.6.1로 설명 하겠습니다.


라이센스 : apache license 2.0


사이트

  공식 : http://people.apache.org/~pmuellr/weinre/docs/latest/Home.html

  1.6.1다운로드 : http://people.apache.org/~pmuellr/weinre/builds/1.x/1.6.1/weinre-jar-1.6.1.zip


1. weinre.jar파일 실행해서 서버시작 하기

01./* 옵션 */
02.-help (or -? or -h) => 도움말
03.-httpPort [포트번호] => 포트번호 (default 8080)
04.-boundHost [hostname | ip address | -all-] => 서버 ip주소 또는 호스트이름
05.-verbose [true false] => 자세한 내용 출력 (default false)
06.-readTimeout [seconds] => weinre서버가 log내용을 읽어들이는 시간 (default 5초)
07. 
08./* 실행 */
09.java -jar weinre.jar --httpPort 포트번호 --boundHost IP주소 --verbose true



2. weinre client 띄우기

http://weinre서버주소:포트번호/client


3. 개발한 html페이지에 weinre script 삽입후 리로드

1.<script type="text/javascript" src="http://서버주소:포트번호/target/target-script-min.js"></script>


4. weinre client에서 target이 접속되었는지 확인



5. 위와같이 접속이 확인되었으면 디버깅이 가능한 상태입니다.

4번 그림에서의 화면은 webkit의 디버깅창이 아닌 webkit의 디버깅창을 

따라서 비슷하게 만든 weinre의 화면입니다.


출처 : http://kdarkdev.tistory.com/248

Posted by 1010
반응형

JSONP

From Wikipedia, the free encyclopedia

JSONP or "JSON with padding" is a communication technique used in JavaScript programs running in web browsers to request data from a server in a different domain, something prohibited by typical web browsers because of thesame-origin policy.

Note that for JSONP to work, a server must know how to reply with JSONP-formatted results. JSONP does not work with JSON-formatted results. The JSONP parameters passed as arguments to a script are defined by the server.

Reason for JSONP[edit]

Under the same-origin policy (SOP)JavaScript code loaded from one domain is not allowed to fetch data from another domain. However, this restriction does not apply to the <script> tag, which can specify a URL of JavaScript code to load from a remote server in a src attribute. This was used to work around the SOP limitations by pointing the src to aweb service returning dynamically generated JavaScript code (JSONP), instead of JSON data. Because the code is loaded by the <script> tag, it can be normally executed and return the desired data block, thus bypassing SOP.

Execution of raw JavaScript from a third party raised security concerns and creates a possible vulnerability.[1] Cross-origin resource sharing (CORS) is a more recent method of getting data from a server in a different domain, which addresses some of those criticisms. All modern browsers now support CORS making it a viable cross-browser alternative.

How it works[edit]

To see how this technique works, first consider a URL request that returns JSON data. A JavaScript program might request this URL via XMLHttpRequest, for example. Suppose the user ID of Foo is 1234. A browser requesting the URLhttp://server2.example.com/Users/1234, passing the ID of 1234, would receive something like:

{
    "Name": "Foo",
    "Id": 1234,
    "Rank": 7
}

This JSON data could be dynamically generated, according to the query parameters passed in the URL.

Here, an HTML <script> element specifies for its src attribute a URL that returns JSON:

<script type="application/javascript"
        src="http://server2.example.com/Users/1234">
</script>

The browser will, in order, download the script file, evaluate its contents, interpret the raw JSON data as a block, and throw a syntax error. Even if the data were interpreted as a JavaScript object literal, it could not be accessed by JavaScript running in the browser, since without a variable assignment object literals are inaccessible.

In the JSONP usage pattern, the URL request pointed to by the <script>'s src attribute returns JSON data, with a function call wrapped around it. In this way, a function that's already defined in the JavaScript environment can manipulate the JSON data. A JSONP payload might look like this:

functionCall({"Name": "Foo", "Id": 1234, "Rank": 7});

The function call is the "P" of JSONP—the "padding" around the pure JSON, or according to some[2] the "prefix". By convention, the browser provides the name of the callback function as a named query parameter value, typically using the name jsonp or callback as the named query parameter field name, in its request to the server, e.g.,

<script type="application/javascript"
        src="http://server2.example.com/Users/1234?jsonp=parseResponse">
</script>

In this example, the received payload would be:

parseResponse({"Name": "Foo", "Id": 1234, "Rank": 7});

Padding[edit]

While the padding (prefix) is typically the name of a callback function that is defined within the execution context of the browser, it may also be a variable assignment, an if statement, or any other JavaScript statement. The response to a JSONP request is not JSON and is not parsed as JSON; the returned payload can be any arbitrary JavaScript expression, and it does not need to include any JSON at all. But conventionally, it is a JavaScript fragment that invokes a function call on some JSON-formatted data.

Said differently, the typical use of JSONP provides cross-domain access to an existing JSON API, by wrapping a JSON payload in a function call.

Script element injection[edit]

JSONP makes sense only when used with a script element. For each new JSONP request, the browser must add a new <script> element, or reuse an existing one. The former option—adding a new script element—is done via dynamic DOM manipulation, and is known as script element injection. The <script> element is injected into the HTML DOM, with the URL of the desired JSONP endpoint set as the "src" attribute. This dynamic script element injection is usually done by a JavaScript helper library. jQuery and other frameworks have JSONP helper functions; there are also standalone options.[3][4][5]

The dynamically injected script element for a JSONP call looks like this:

<script type="application/javascript"
        src="http://server2.example.com/Users/1234?jsonp=parseResponse">
</script>

After the element is injected, the browser evaluates the element, and performs an HTTP GET on the src URL, retrieving the content. Then the browser evaluates the return payload as JavaScript. This is typically a function invocation.

In that way, the use of JSONP can be said to allow browser pages to work around the same-origin policy via script element injection.

The script runs within the scope of the including page and, as such, is still subject to cross-domain restrictions relative to the including page's domain. This means that one cannot, for example, load a library hosted on another site via JSONP and then make XMLHttpRequest requests to that site (unless CORS is supported) although one could use such a library to make XMLHttpRequests to one's own site.

Cross-domain requests using a proxy server[edit]

The JavaScript same-origin policy normally prevents browsers from sending AJAX requests to a different domain and receiving a response (newer browsers that support CORS can relax this constraint). A cooperating proxy server, however, does not have such restrictions and can relay a browser request to a server in a separate domain, store the result, and then return that JSON payload when the browser makes a second request. The server would be instructed within the first request to store the output (POST returning JSON payload) temporarily into a local store (for example memcached or within a session variable), and a second request from the browser then would fetch the cached response to the initial query.[6] The xd_arbiter.php used by Facebook's JS SDK is a popular example of this cooperating server technique.[7]

Security concerns[edit]

Including script tags from remote servers allows the remote servers to inject any content into a website. If the remote servers have vulnerabilities that allow JavaScript injection, the page served from the original server is exposed to an increased risk. If an attacker can inject any JavaScript into the original web page, then that code can retrieve additional JavaScript from any domain. The Content Security Policy HTTP Header lets web sites tell web browsers which domains scripts should be included from.

An effort is underway to define a safer strict subset definition for JSON-P[8] that browsers would be able to enforce on script requests with a specific MIME type such as "application/json-p". If the response didn't parse as strict JSON-P, the browser could throw an error or just ignore the entire response. For the moment however the correct MIME type is "application/javascript" for JSONP.[9]

Cross-site request forgery[edit]

Native deployments of JSONP are subject to cross-site request forgery (CSRF or XSRF) attacks.[10] Because the HTML<script> tag does not respect the same-origin policy in web browser implementations, a malicious page can request and obtain JSON data belonging to another site. This will allow the JSON-encoded data to be evaluated in the context of the malicious page, possibly divulging passwords or other sensitive data if the user is currently logged into the other site.

This is problematic only if the JSON-encoded data contains sensitive information which should not be disclosed to a third party, and the server depends on the browser's same-origin policy to block the delivery of the data in the case of an improper request. There is no problem if the server determines the propriety of the request itself, only putting the data on the wire if the request is proper. Cookies are not by themselves adequate for determining if a request was authorized. Exclusive use of cookies is subject to cross-site request forgery.

History[edit]

In July 2005 George Jempty suggested an optional variable assignment be prepended to JSON.[11][12] The original proposal for JSONP, where the padding is a callback function, appears to have been made by Bob Ippolito in December 2005[13] and is now used by many Web 2.0 applications such as Dojo ToolkitGoogle Web Toolkit and Web services.

An unnamed process equivalent to JSONP has been used by PostX envelopes (now owned by Cisco Systems and deployed on Cisco's Email Security Appliance and Cisco Registered Envelope Service (CRES)) since May 2002.

See also[edit]

References[edit]

External links[edit]


Posted by 1010
05.JSP2014. 4. 1. 16:53
반응형
출처 : http://warmz.tistory.com/739

Ajax 로 다른 도메인에 있는 url 을 호출해 데이터나 HTML을 가져오는건 보안상 안된다고 한다. 되면 참 좋을텐데;;


뭐 아무튼 이걸 해결하기 위한 방법으로 JSONP 라는 형식으로 호출하던가 아니면 Proxy Servlet 을 하나 맹글어 그 서블릿을 거쳐 HttpClient 로 가져오는 방법, 훌래쉬를 이용하는 방법이 있다고 한다.!

그중에서 이번엔 JSONP 형식으로 호출하는 방법을 연구해 보겠다.

JSONP 형식이란 뭐 별건 아닌것 같고 기존에 서버에서 리턴해 주던 

{"key1" : "value1",  "key2" : "value2"} 요런 json 문자열을 

callback({"key1" : "value1",  "key2" : "value2"}); 요런식으로 임의의 함수를 호출해 주는 형식의 문자열로 리턴해 주는것을 말하는것 같다.

즉, jsonp 로 ajax 호출을 하기 위해선 아무 url 이나 안되고  callback({"key1" : "value1",  "key2" : "value2"});  요런식으로 함수안에 json 문자열이 들어간 형식으로 서버에서 리턴을 해줘야 가능하다.

각설하고 jQuery를 활용해 맹글어 보자.



jQuery에서 jsonp 호출하는 방법#1
1
2
3
    //d.key;
});

jQuery에서 jsonp 호출하는 방법#2
1
2
3
4
5
6
7
8
$.ajax({
    dataType : "jsonp",
    jsonp : "callback",
    success : function(d){
        // d.key;
    }
});

방법#1 이나 방법#2는 작동하는게 동일하다. 취향에 맞게 쓰임새에 맞게 쓰면된다. 개인적으로 방법#2 를 여러가지 원하는 ajax 호출 옵션을 줄수 있어서 더 좋아한다.

살짝 설명해 보면 방법#2 에서 쓴 ajax 옵션중 jsonp는 데이터를 넘겨줄 서버에서 받는 callback 함수명 파라메터이다. 서버에 따라 원하는 callback 함수명을 적어줘야 한다. 방법#1을 보면 대충 이해할 수 있다.

jsonp 옵션에다 적어준 함수명은 ajax 호출 url 뒤에다 방법#1에서 처럼 파라메터 형식으로 자동 추가된다.



전체소스코드 client.html
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
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>Jsonp test with jquery</title>
     
    <script type="text/javascript" src="/resource/js/jquery-1.6.2.min.js"></script>
    <script>
        $(document).ready(function(){
            $("#testBtn").click(function(){
                $.getJSON("http://127.0.0.1:8080/server/data.jsp?callback=?", function(d){
                    $.each(d, function(k, v){
                        $("#getjson").append("<div>" + k + " : " + v + "</div>");
                    });
                    $("#getjson").show();
                });
                             
                $.ajax({
                    url : "http://127.0.0.1:8080/server/data.jsp",
                    dataType : "jsonp",
                    jsonp : "callback",
                    success : function(d){
                        $.each(d, function(k, v){
                            $("#ajax").append("<div>" + k + " : " + v + "</div>");
                        });
                        $("#ajax").show();
                    }
                });
            });
        });
    </script>
     
    <style>
        div{margin-bottom:10px;padding:2px;}
        #getjson{border:1px solid red;display:none;}
        #ajax{border:1px solid blue;display:none;}
    </style>
</head>
 
<body>
    <button id="testBtn">테스트!</button>
    <div id="getjson"></div>
    <div id="ajax"></div>
</body>
</html>



다음으로 간단한 테스트를 위해 초간단 심플 데이터 제공용 jsp 파일을 하나 맹글어 보자. JSON 변환용 라이브러리로 Jackson JSON Processor를 사용했다.
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
<%@ page language="java" contentType="text/javascript; charset=UTF-8" pageEncoding="UTF-8"%>
 
<%@ page import="java.io.StringWriter"%>
<%@ page import="java.util.HashMap"%>
<%@ page import="java.util.Map"%>
 
<%@ page import="org.codehaus.jackson.map.ObjectMapper"%>
 
<%
    Map<String, String> dummyData = new HashMap<String, String>();
    dummyData.put("value1", "값1");
    dummyData.put("value2", "값2");
    dummyData.put("value3", "값3");
    dummyData.put("value4", "값4");
     
    StringWriter sw = new StringWriter();
     
    // Jackson JSON Mapper 를 사용해서 Map 을 JSON 문자열로 변환
    ObjectMapper mapper = new ObjectMapper();
    mapper.writeValue(sw, dummyData);
     
    request.setAttribute("sw", sw);
%>
 
<%-- ajax 에서 넘겨준 callback 함수 파라메터 가져오기 --%>
${param.callback}(${sw});
ajax로 호출한 url 경로에 맞게금 /server/data.jsp 로 저장하고 http://localhost:8080/client.html 로 접속해보자. 왜냐하면 localhost 랑 127.0.0.1 은 도메인이 다르니깐.  

음 잘 작동된다~~ 초간단 심플 예제이기 때문에 간단하게 JSP로 구현했는데 다음번에 쫌더 실제적으로 프로젝트에 써먹을수 있도록 Spring으로 예제를 하나 맹글어 봐야긋다~

[샘플소스]CrossDomain1.war


Posted by 1010
98..Etc/jQuery2014. 4. 1. 16:47
반응형

출처 : http://findfun.tistory.com/m/post/382


jQuery.ajax()

원문 링크  http://api.jquery.com/jQuery.ajax/

권고사항 : 아래 글을 보시기 전에 권고드립니다. 아래는 발번역과 오역 그리고 미처 다 한글화가 되어있지 않습니다. 의미도 모른채 번역된 부분이 많기 때문에 다 건너띠고 아래쪽 예제만 보시길 강력히 권고 드립니다. 나빠진 정신건강에 대해 책임(?)지지 않습니다. ^^;;;;

jQuery.ajax( url [, settings] )Returns : jqXHR

개요 : 비동기 HTTP (Ajax) 요청을 수행합니다.

  • jQuery.ajax( url [, settings] )
  • url 요청을 보낼 URL 문자열
  • settings key/value 쌍으로 구성된 Ajax 요청 설정값. 모든 값들은 생략이 가능한 옵션값 임. 기본적인 설정값을 $.ajaxSetup() 에 정의할 수 있음. 모든 세팅에 대한 내용이 궁금하시면 jQuery.ajax( settings ) 을 참고하세요.
  • jQuery.ajax( settings )
  • settings key/value 쌍으로 구성된 Ajax 요청 설정값. 모든 값들은 생략이 가능한 옵션값 임. 기본적인 설정값을 $.ajaxSetup() 에 정의할 수 있음.
  • acceptsMap
    Default: 데이터 타입에 의존적 depends on DataType

    content 타입을 헤더에 포함하여 서버에 보내면 응답 시 같은 타입으로 리턴이 됩니다. 만약 accepts 세팅값을 수정하려 한다면 $.ajaxSetup() 함수에서 해야 합니다.

    asyncBoolean
    Default: true

    기본으로 사용하면, 모든 요청은 비동기방식으로 동작합니다. 만일 동기방식으로 사용하려면 이 값을 false로 세팅하세요. 크로스도메인(2개의 도메인 사이의 정보교환)과 dataType: "jsonp" 인 경우는 동기방식이 지원되지 않습니다. 동기방식은 요청이 처리될 때까지 브라우져가 일시적인 잠금상태가 됩니다.

    beforeSend(jqXHR, settings)Function

    요청 전 콜백함수이며, 이 함수에서 요청을 보내기 전 jqXHR 객체를 수정할 수 있습니다. 이 함수에서 false를 반환하면 Ajax 요청이 취소됩니다.jQuery 1.5부터 beforeSend 옵션은 요청의 type에 상관없이 호출할 수 있습니다.

    cacheBoolean
    Default: true, dataType 이 'script' 와 'jsonp' 일때는 false로 세팅

    만일 이 값을 false로 하면, 브라우저의 캐쉬사용을 강제적으로 막습니다. 또한 false 세팅하면 URL 쿼리 스트링에 "_=[TIMESTAMP]" 값이 추가됩니다.

    complete(jqXHR, textStatus)Function, Array

    요청이 완료되었을 때 호출되는 함수입니다. 요청에 대한 응답이 success 나 error 가 반환된 후 실행됩니다. 이 함수는 2개의 인자를 갖습니다. jqXHR 객체와 요청에 대한 상태값("success""notmodified""error""timeout""abort""parsererror")으로 구성되어 있습니다. 더 자세한 내용은Ajax Event를 참고하십시오.

    contents(added 1.5)Map

    문자열과 정규표현식이 쌍으로 이루어진 맵 데이터 입니다. jQuery는 응답 데이터를 이 맵 데이터를 기준으로 파싱합니다.

    contentTypeString
    Default: 'application/x-www-form-urlencoded'

    서버에 데이터를 보낼 때 사용되는 content-type 입니다. 기본값은 "application/x-www-form-urlencoded" 입니다. 명시적으로 바꾸려면 $.ajax() 함수안에서 content-type을 세팅해 줘야 합니다. 서버로 데이터를 보낼 때는 언제나 UTF-8 charset를 사용합니다. 따라서 서버 사이드 프로그램 시 그에 맞게 디코딩을 하여 사용해야 합니다.

    contextObject

    This object will be made the context of all Ajax-related callbacks. By default, the context is an object that represents the ajax settings used in the call ($.ajaxSettings merged with the settings passed to $.ajax). For example, specifying a DOM element as the context will make that the context for the complete callback of a request, like so:

    $.ajax({
    	  url: "test.html",
    	  context: document.body
    	}).done(function() { 
    	  $(this).addClass("done");
    	});

    converters(added 1.5)Map
    Default: {"* text": window.String, "text html": true, "text json": jQuery.parseJSON, "text xml": jQuery.parseXML}

    데이터 타입을 변환합니다.

    crossDomain(added 1.5)Boolean
    Default: false : 같은 도메인 내의 요청일 경우, true : 크로스 도메인 간의 요청일 경우

    만일 2개의 다른 도메인(CrossDomain)간의 데이터 교환이라면(JSONP와 같은), 이 세팅값을 true로 해야 합니다.

    dataObject, String

    서버로 보낼 데이터입니다. GET 요청 형태의 query 스트링으로 변환되어 보내집니다. GET 요청 파라미터에 자동으로 추가됩니다. 이런 자동 추가를 방지하기 원하면 processData 옵션을 보시기 바랍니다. 이 객체는 key/value의 쌍으로 이루어져 있습니다. 만일 value가 배열이라면, jQuery는 같은 key로 여러 value를 직렬화 구성을 하게 됩니다. 아래쪽에 추가적인 설명이 있습니다.

    dataFilter(data, type)Function

    이 함수는 응답 원시 데이터를 핸들링 할 수 있습니다. 정제된 데이터를 반활해야 할 필요가 있을 때 사용합니다. 두개의 인자가 있는데 data 와 그 데이터의 type입니다.

    dataTypeString
    Default: Intelligent Guess (xml, json, script, or html)

    서버에서 응답 받을 때는 데이터의 타입을 jQuery가 추정하여 처리합니다. 만일 인자를 아무것도 적지 않으면 응답 메시지의 MIME type을 기초로하여 처리하게 되는 것입니다. MIME type이 XML 이며 yield XML을 생성하고, 1.4 JSON은 JavaScript 객체를 생성, 1.4 script라면 script를 실행하고, 그 외 다른 것들은 문자열을 리턴합니다.

    • "xml": jQuery가 XML 문서를 반환합니다.
    • "html": 평문 HTML 을 반환합니다.
    • "script": JavaScript를 실행하고 평문 텍스트를 리턴합니다. 쿼리 스트링에 "_=[TIMESTAMP]" 를 추가하면 캐싱을 방지할 수 있습니다. 이런 방식은cache 옵션을 true로 바꾸는 역할을 합니다.
    • "json": JSON을 JavaScript 객체형태로 반환합니다. jQuery 1.4에서 JSON 데이터는 엄격한 방식으로 파싱되었습니다. 형식에 맞지않는 JSON 데이터는 요청이 거부되고 error을 발생시켰습니다. JSON 포맷에 대해 궁금하시면 json.org 을 방문해 보세요.
    • "jsonp": JSONP 를 사용하여 JSON 블럭을 로드합니다. 쿼리 스트링에 "_=[TIMESTAMP]" 를 추가하면 캐싱을 방지할 수 있습니다. 이런 방식은 cache옵션을 true로 바꾸는 역할을 합니다.
    • "text": 평문 텍스트 문자열을 반환합니다.
    • multiple, 공백 구분 값(space-separated values): jQuery 1.5에서, dataType을 변환할 수 있게 되었습니다. 예를들어 응답받은 text 를 XML 로 변화하고 싶으면, "text xml"이라고 사용하면 됩니다.

    error(jqXHR, textStatus, errorThrown)Function

    요청(request)이 실패하면 호출됩니다. 이 함수는 3개의 인자를 통해 데이터를 받을 수 있습니다. jqXHR 객체는 발생한 에러 타입과 추가적인 예외 사항을 담고 있습니다. 두번째 인자에는 "timeout""error""abort""parsererror" 와 같은 상황을 담고 있습니다. 세번째 인자에는 HTTP 에러가 담겨 있는데, "Not Found" 나 "Internal Server Error." 같은 것 들입니다. Note: cross-domain 스크립트나 JSONP 요청에 대해서는 이 함수를 사용할 수 없습니다.

    globalBoolean
    Default: true

    전역 Ajax 이벤트 핸들러를 제어합니다. 기본값은 true 입니다. 이 값을 false로 하면 ajaxStart 나 ajaxStop 같은 전역 핸들러의 실행을 막을 수 있습니다.

    headers(added 1.5)Map
    Default: {}

    요청 시 추가로 보낼 헤더 정보입니다. key/value 쌍으로 구성됩니다. 이 세팅값은 beforeSend 함수가 호출되기 전에 처리되야 합니다. beforeSend 함수 내에서 value 값을 재조정 할 수 있습니다.

    ifModifiedBoolean
    Default: false

    마지막 request 이후 response가 변경되었을 경우에만 request가 성공하도록 허용하는 값입니다. 이것은 마지막 수정 정보를 헤더에서 체크하는 것입니다. 기본값은 false 이며 이 옵션이 무시됩니다. 즉, 언제나 request에 대한 응답을 체크하는 것입니다. jQuery 1.4 부터는 수정되지 않은 데이터를 알아내기 위한 'etag' 를 체크할 수 있습니다.

    isLocal(added 1.5.1)Boolean
    Default: 현재 프로토콜을 유지 depends on current location protocol

    jQuery에서 인식하지 못하더라도 현재 환경이 "local(예, filesystem)" 로 인식할 수 있도록 허용합니다.(이건 무슨 의미인지 모르겠네요.) 다음 file*-extensionwidget 프로토콜 들은 현재 local로 인식합니다. 만일 isLocal 세팅을 변경을 원하시면 $.ajaxSetup() 함수에서 하실 것을 권장드립니다.

    jsonpString

    jsonp 요청에 사용한 콜백 함수명을 오버라이드 합니다. 이 값은 url에 포함된 쿼리 스트링의 부분인 'callback=?' 문자열 중 'callback' 을 대신하여 사용됩니다. 예를 들면 {jsonp:'onJSONPLoad'} 라고 세팅하면 서버에 'onJSONPLoad=?' 처럼 전달되게 되는 것입니다. jQuery 1.5 부터는 jsonp 옵션을false 로 세팅하여 URL에 "?callback" 이 추가되는 것을 방지하거나 "=?" 을 변조되는 시도를 방지할 수 있습니다. 이러한 경우 명시적으로jsonpCallback 세팅값을 이용하여야 합니다. 예를 들어, { jsonp: false, jsonpCallback: "callbackName" } 와 같이 사용합니다.

    jsonpCallbackString, Function

    JSONP 요청 시 콜백 함수명을 지정합니다. 지정하지 않으면 jQuery에서 임의적으로 부여하게 됩니다. 요청(request)에 대해 쉽게 핸들링 할 수 있도록 유니크한 이름이 부여됩니다. 콜백 이름을 당신이 지정할 수도 있습니다. jQuery 1.5부터 함수명을 세팅할 수 있게 되어습니다.

    mimeType(added 1.5.1)String

    XHR의 마임 타입을 설정합니다.

    passwordString

    HTTP 엑세스 시 패스워드를 설정합니다.

    processDataBoolean
    Default: true

    By default, data passed in to the data option as an object (technically, anything other than a string) will be processed and transformed into a query string, fitting to the default content-type "application/x-www-form-urlencoded". If you want to send a DOMDocument, or other non-processed data, set this option to false.

    scriptCharsetString

    Only for requests with "jsonp" or "script" dataType and "GET" type. Forces the request to be interpreted as a certain charset. Only needed for charset differences between the remote and local content.

    statusCode(added 1.5)Map
    Default: {}

    요청에 대한 응답 시 전달된 HTTP 상태 코드와 실행될 함수로 이루어진 집합입니다. 예를 들어, 404 상태에 대해 알림창을 보여주는 경우는 아래 예와 같습니다.

    $.ajax({
    	  statusCode: {
    		404: function() {
    		  alert("page not found");
    		}
    	  }
    	});

    만일 요청이 성공했다면, 상태코드는 성공 콜백함수로 같은 파라미터를 전달합니다. 반대로 error 가 발생해도 같은 파라미터를 error 콜백 함수로 전달하게 됩니다.

    success(data, textStatus, jqXHR)Function, Array

    요청이 성공했을 때 호출됩니다. 이 함수는 3개의 인자를 전달합니다. data 인자는 서버에서 전달된 데이터를, 두번째는 데이터의 타입을, 마지막으로 jqXHR(jquery 가 변형한 XMLHttpRequest 객체)를 전달하게 됩니다. jQuery 1.5 부터, success 시 함수 배열을 전달 받을 수 있습니다.

    timeoutNumber

    요청 대기 시간을 세팅합니다.

    traditionalBoolean

    이 세팅값을 true로 하면 전통적인 스타일의 파라미터 직렬화를 사용할 수 있습니다.(이건 뭔가요 ㅡㅡ;;)

    typeString
    Default: 'GET'

    요청 시 POST 와 GET 방식을 결정합니다. 기본값은 GET 방식입니다.

    urlString
    Default: 현재 페이지 The current page

    요청을 보낼 URL 주소입니다.

    usernameString

    HTTP 요청 시 필요한 username 값 입니다.

    xhrFunction
    Default: IE 에서는 ActiveXObject 이고 다른 브라우저는 XMLHttpRequest

    XMLHttpRequest 객체입니다.

    xhrFields(added 1.5.1)Map

    기본 XHR 객체의 키-값의 맵 데이터 입니다. 예를 들어, 크로스 도메인에서 withCredentials 값을 true로 하고 싶다면 아래와 같이 세팅합니다.

    $.ajax({
    	   url: a_cross_domain_url,
    	   xhrFields: {
    		  withCredentials: true
    	   }
    	});

    jQuery 1.5 부터 withCredentials 속성은 네이티브 XHR 에서 전달하지 못합니다.

$.ajax() 함수는 jQuery에서 사용되는 모든 Ajax 의 근간입니다. 종종 이 함수를 직접 호출하지 않아도 쉽게 사용할 수 있는 함수들이 있습니다.$.get() 이나 .load() 같은 함수들이 그것들입니다. 만일 세팅값을 변경할 필요가 있을 경우에도 $.ajax() 함수에서 유연하게 변경할 수 있습니다.

$.ajax();

Note: 기본 세팅값을 전역적으로 관리하려면 $.ajaxSetup() 함수를 이용해야 합니다.

위의 옵션값을 아무것도 없이 사용하면 현재 페이지에서 응답 결과를 제어하지 못합니다. 이게 가능하려면 콜백 함수를 지정해야 합니다.

The jqXHR Object

jQuery XMLHttpRequest (jqXHR) 객체는 $.ajax() 함수에서 반환됩니다. jQuery 1.5 부터 브라우저의 네이티브 XMLHttpRequest 객체의 상위집합 입니다. 예를 들어, 이 객체는 responseText 과 responseXML 속성을 포함하고 있을 뿐만 아니라 getResponseHeader() 함수도 포함하고 있습니다. 전송 메카니즘이 XMLHttpRequest 가 아닌 다른 것일 경우( JSONP 요청에 대한 script 태그 같은) jqXHR 객체는 네이티브 XHR 기능을 이용하게 됩니다.

jQuery 1.5.1부터, jqXHR 객체는 overrideMimeType() 함수를 사용하게 됩니다. (이것은 jQuery 1.4.x 에서는 사용되었지만, jQuery 1.5 에서 일시적으로 삭제되었음). .overrideMimeType() 함수는 method may be used in the beforeSend() 콜백 함수에서 사용될 수 있습니다. 예를 들어, 응답의 content-type header 를 수정하기 위해서 아래와 같이 사용할 수 있습니다.:

$.ajax({
  url: "http://fiddle.jshell.net/favicon.png",
  beforeSend: function ( xhr ) {
    xhr.overrideMimeType("text/plain; charset=x-user-defined");
  }
}).done(function ( data ) {
  if( console && console.log ) {
    console.log("Sample of data:", data.slice(0, 100));
  }
});

$.ajax() 에서 반환된 jqXHR 객체는 jQuery 1.5 의 약속된 인터페이스를 구현하여 모든 속성, 메소드, 동작들을 제공하고 있습니다.(더 많은 정보를 원하시면 Deferred object 를 참고). 편의성과 일관성을 위해 $.ajax() 함수에서 사용될 콜백 함수들로 jqXHR 객체는 .error().success().complete()와 같은 함수들을 사용할 수 있습니다. 이들 함수들은 $.ajax() 요청이 종료되었을 때 호출되고 모두 같은 인자를 전달받게 됩니다. 이것은 단일 요청에서 여러 콜백 함수를 지정할 수도 있고 요청이 완료된 후에도 콜백 함수를 지정할 수 있습니다.

Notice: jqXHR.success()jqXHR.error()jqXHR.complete() 콜백 사용은 1.8 버전부터 사용이 중지됩니다. 이런 사용을 제거하거나 jqXHR.done(),jqXHR.fail()jqXHR.always() 함수들로 대체하십시오.

// Assign handlers immediately after making the request,
// and remember the jqxhr object for this request
var jqxhr = $.ajax( "example.php" )
    .done(function() { alert("success"); })
    .fail(function() { alert("error"); })
    .always(function() { alert("complete"); });

// perform other work here ...

// Set another completion function for the request above
jqxhr.always(function() { alert("second complete"); });

For backward compatibility with XMLHttpRequest 이전 버젼과의 호환성을 위해, jqXHR 객체는 아래와 같은 속성과 메소드들을 제공합니다.

  • readyState
  • status
  • statusText
  • responseXML or responseText
  • setRequestHeader(name, value)
  • getAllResponseHeaders()
  • getResponseHeader()
  • abort()

하지만 onreadystatechange 매커니즘은 제공되지 않기 때문에 successerrorcompletestatusCode 이 상황들을 모두 커버 해야할 필요성이 있습니다.

Callback Function Queues

beforeSenderrordataFiltersuccesscomplete 옵션들 모두는 적절한 시간에 호출할 수 있는 콜백 함수를 가질 수 있습니다.

jQuery 1.5부터, error (fail), success (done), complete (always) 콜백 함수들은 큐에서 선입선출(first-in, first-out) 방식으로 제어할 수 있습니다. 이 의미는 콜백 함수마다 처리 로직을 수행할 수 있다는 뜻입니다. Deferred object methods 를 참고하여 $.ajax() 함수에서 콜백 시의 내부처리에 대해 알아볼 수 있습니다.

모든 콜백 함수의 this 키워드는 $.ajax 에서 전달된 context 의 객체들을 가르킵니다. 만일 context 가 지정되지 않았다면 this는 Ajax 세팅 자체를 지칭하게 됩니다.

JSONP 나 cross-domain 의 GET 요청 같은 XHR을 사용하지 않는 Ajax 방식을 사용할 경우에 XMLHttpRequest 나 textStatus 파리미터들은 undefined값을 가지게 됩니다.

아래는 $.ajax()에서 콜백 시 발생하는 훅(hook - I/O 시 정의된 상수값들 정도로 생각하면 됨) 값들 입니다.

  1. beforeSend jqXHR 객체와 파라미터 settings 맵을 받습니다.
  2. error 요청이 실패했을 경우 순서대로 등록됩니다. error 타입 문자열과 exception 객체로 구성된 jqXHR 들을 받습니다. 몇몇 Some 내장 error들은 exception 객체에 "abort", "timeout", "No Transport"와 같은 문자열이 넘어옵니다.
  3. dataFilter 성공적으로 응답이 되었을 경우 즉시 호출됩니다. 반환된 데이터와 dataType 을 받을 수 있고 success 쪽으로 변경된 데이터를 전달해야 합니다.
  4. success 요청이 성공하면 요청된 순서에 따라 호출됩니다. 반환된 데이터와 성공 코드를 포함한 문자열 그리고 jqXHR 객체를 받을 수 있습니다.
  5. complete 요청이 실패하거나 성공에 관계없이 요청이 종료되면 순서에 따라 발생합니다. 성공 또는 실패에 대한 코드를 담은 jqXHR 객체를 받습니다.

예를 들어, HTML 이 반환되고 이것을 사용하고 싶다면 success 핸들러를 사용해야 합니다.

$.ajax({
  url: 'ajax/test.html',
  success: function(data) {
    $('.result').html(data);
    alert('Load was performed.');
  }
});

Data Types

$.ajax() 함수는 검색한 데이터에 대한 정보를 제공하는 서버에 의존합니다. 만일 서버에서 XML 데이터가 제공되었다면, 일반적인 XML 메소드나 jQuery의ㅣ 선택자(selector)들을 사용하여 제어할 수 있습니다. 만일 위의 예제와 같이 HTML 같은 것이라면 데이터를 text 처럼 취급할 수도 있습니다.

별개의 다른 데이터를 dataType 옵션을 이용하여 다룰 수 있습니다. dataType 으로는 xml htmljsonjsonpscripttext.

text 나 xml 타입은 jqXHR 객체의 속성인 responseText 나 responseXML 을 통해 success 핸들러에서 간단하게 받을 수 있습니다.

Note: 웹 서버에서 사용한 MIME 타입과 데이터 요청 시의 dataType 값이 같은지 확인해야 합니다. 특히 XML 은 서버에서 text/xml 또는application/xml 로 반환했는지 확인하고 그에 맞춰 사용해야 합니다.

만일 html 을 지정하는 경우, HTML 이 반환 되기 전에 내부의 JavaScript 는 실행이 된 후 반환이 됩니다. 비슷하게 script 를 정의했다면, 서버에서 반환될 때 인라인 JavaScript 는 실행이 되고 반환되게 됩니다.

json 타입은 The json JavaScript 객체로 가져온 데이터 파일을 분석하고 결과 데이터로 만들어진 객체를 반환합니다. 이렇게 하기 위해서는, 브라우저가 지원한다면 jQuery.parseJSON() 을 사용하거나, 지원하지 않는다면 Function constructor 을 사용해야 합니다. 형식에 맞지 않는(Malformed) JSON 데이터는 에러가 발생하게 되는데 더 많은 정보는 json.org에서 보실 수 있습니다. JSON 데이터는 구조화된 데이터의 이동에 편리합니다. JavaScript 로 처리하기에 간결하고 쉽습니다. 만일 외부 서버에서 가져와야 하는 데이터라면, jsonp 타입을 대신 사용할 수 있습니다.

이 jsonp 타입은 URL 쿼리스트링에 callback=? 이라는 문자열이 추가됩니다. 서버는 유효한 형태의 JSONP 반환 데이터를 콜백(callback) 이름을 사용하여 반환하게 됩니다. $.ajax() 의 옵션인 callback 이외에 다른 파라미터를 지정하여 사용할 수 있습니다.

Note: JSONP 는 확장된 JSON 포맷입니다.

script 나 jsonp 데이터 타입이 사용 가능한 원격 서버에서 데이터를 가져왔을 때, error 콜백과 글로벌 이벤트는 발생하지 않습니다.

Sending Data to the Server

기본적으로, Ajax는 GET HTTP 방식입니다. POST 방식이 필요할 경우, type 옵션값을 이용하면 됩니다. POST 데이터가 서버로 전송될 경우 W3C XMLHTTPRequest 표준인 UTF-8 캐릭터셋을 이용하게 됩니다.

data 옵션값은 key1=value1&key2=value2 형태의 쿼리 스트링을 사용할 수 있습니다. 또한 {key1: 'value1', key2: 'value2'} 형태도 사용이 가능합니다. 만일 후자의 형태를 사용할 경우, 데이터를 보내기 전에 jQuery.param()을 사용하여 데이터를 가공해야 합니다. 이 과정은 processData 을 false로 세팅하면 해결할 수 있습니다. 이 과정을 수행하면 서버로 XML 데이터를 보낼 때 contentType 타입이 application/x-www-form-urlencoded 로 변경되는 것을 방지할 수 있습니다. (음, 이 부부은 사실 명확치 않네요. 좀더 공부가 필요합니다. ㅜㅜ)

Advanced Options

global 옵션으로 .ajaxSend().ajaxError() 그리고 이 함수로 인해 호출되는 함수들의 실행을 제어할 수 있습니다. cross-domain 스크립트와 JSONP 가 사용될 경우에는 자동으로 false 로 세팅됩니다. 더 자세한 내용은 함수들의 사용법을 살펴 보십시오.

만일 서버가 HTTP 인증을 요구한다면 username 과 password 옵션을 사용할 수 있습니다.

Ajax 사용 시 시간제한을 두어 사용자에게 그 내용을 제공하는 것이 좋습니다. 요청시간은 $.ajaxSetup() 에서 timeout 옵션값을 조절하는 것이 좋습니다.

기본적으로 지속적인 요청에 대해 브라우저는 캐시에 있는 결과를 사용하려 합니다. 이런 부분을 해결하기 위해 cache 옵션을 false로 세팅하시기 바랍니다. 또한 결과가 마지막 요청 후에 변경되지 않았다면 ifModified을 true로 세팅하면 false를 반환받을 수 있습니다.

scriptCharset 옵션은 <script> 태그의 캐릭터셋을 명시적으로 설정할 수 있습니다. 만약 서버와 스크립트의 캐릭터 셋이 다를 경우 아주 유용한 옵션입니다.

Ajax 의 기본은 "비동기(asynchronous)" 입니다. async 옵션은 기본적으로 $.ajax() 에서 true 로 세팅되어 있습니다. 이 옵션을 false 로 바꾸면 동기식으로 전환됩니다.

$.ajax() 함수는 XMLHttpRequest 객체를 반환합니다. 일반적으로 jQuery는 내부적으로 이 객체를 처리합니다. 사용자 정의 함수에서는 xhr 의 옵션을 이용해서 가공을 할 수 있습니다. 반환된 객체는 대체로 삭제되지만 저수준 인터페이스에서는 요청에 대한 조작을 위해 사용할 수도 있습니다. 특히,.abort() 를 호출하면 객체가 완성되기 전에 요청을 중단할 수 있습니다.

jQuery.ajaxSettings.xhr 를 오버라이드해서 사용하는 예제입니다.

var _super = jQuery.ajaxSettings.xhr;
jQuery.ajaxSettings.xhr = function () {
    var xhr = _super(),
        getAllResponseHeaders = xhr.getAllResponseHeaders;

    xhr.getAllResponseHeaders = function () {
        if ( getAllResponseHeaders() ) {
            return getAllResponseHeaders();
        }
        var allHeaders = "";
        $( ["Cache-Control", "Content-Language", "Content-Type",
                "Expires", "Last-Modified", "Pragma"] ).each(function (i, header_name) {

            if ( xhr.getResponseHeader( header_name ) ) {
                allHeaders += header_name + ": " + xhr.getResponseHeader( header_name ) + "\n";
            }
            return allHeaders;
        });
    };
    return xhr;
};

Extending Ajax

jQuery 1.5부터, jQuery의 Ajax 는 더 유연하게 사용할 수 있도록 확장된 사전필터(prefilters), 컨버터(converters), 변환(transports)이 포함되어 있습니다. 이런 이점에 대해 더 많은 정보를 얻으시려면 Extending Ajax 페이지를 살펴 보십시오.

Additional Notes:

보안 문제로 인해 대부분의 "Ajax" 요청은 제한이 있습니다. 도메인, 서브 도메인, 프로토콜이 다른 상황에서의 조회는 사용하지 못합니다. Script 와 JSONP 요청은 이런 제약에서 자유롭습니다.

예 제  
서버에 데이터를 보내고 완료되면 사용자에게 알립니다.

$.ajax({
  type: "POST",
  url: "some.php",
  data: { name: "John", location: "Boston" }
}).done(function( msg ) {
  alert( "Data Saved: " + msg );
});

 

예 제  
HTML 페이지의 최신 버전을 요청합니다.

$.ajax({
  url: "test.html",
  cache: false
}).done(function( html ) {
  $("#results").append(html);
});

 

예 제  
XML 데이터를 서버에 보냅니다. processData 옵션값을 false로 하여 자동으로 데이터가 string으로 변환되는 것을 방지합니다.

var xmlDocument = [create xml document];
var xmlRequest = $.ajax({
  url: "page.php",
  processData: false,
  data: xmlDocument
});

xmlRequest.done(handleResponse);

 

예 제  
서버로 데이터를 보내고, 서버는 저장 후 특정 메시지를 보내 줍니다. 완료되면 로그 메시지를 갱신하고 실패하면 알림창을 나타냅니다.

var menuId = $("ul.nav").first().attr("id");
var request = $.ajax({
  url: "script.php",
  type: "POST",
  data: {id : menuId},
  dataType: "html"
});

request.done(function(msg) {
  $("#log").html( msg );
});

request.fail(function(jqXHR, textStatus) {
  alert( "Request failed: " + textStatus );
});

 

예 제  
JavaScript 파일을 로드하고 실행합니다.

$.ajax({
  type: "GET",
  url: "test.js",
  dataType: "script"
});

 

 

조금 쉬어가면서 작성했지만, 역시 역부족이네요. 사실 너무 길어서 필요한 것만 할까 생각했지만 그래도 처음부터 발번역을 했습니다. 나중에 개정판(?)이 될지는 모르겠지만 아마 고쳐야 할 부분이 너무 많습니다. 맨위에서 권고 드렸듯이 예제만 보는 것이 정신건강에 좋을 듯합니다. ^^;;;;;

그럼 즐프하세요.

※ 본 예제는 http://www.jquery.com 에 있는 내용임을 밝힙니다.

Posted by 1010
00.scala2014. 3. 28. 15:38
반응형

Scala file FAQ: How do I open and read files in Scala?

When you're writing Scala scripts, you often want to read text files. Fortunately it's pretty easy to openand read from a file in Scala. You can just use an approach like this:

import scala.io.Source

val filename = "fileopen.scala"
for (line <- Source.fromFile(filename).getLines()) {
  println(line)
}

As you can see, this approach uses the scala.io.Source class. Within the for loop I can now access each line of the file using the 'line' object, and in this case I'm printing each line using println.

A variation of this is to add the mkString function to the file-reading portion of that code, like this:

val fileContents = Source.fromFile(filename).getLines.mkString

Another nice file-reading example comes from Bruce Eckel's website:

val fileLines = io.Source.fromFile("Colors.scala").getLines.toList
fileLines.foreach(println)

As you can see from that example, you can read an entire text file into a Scala List with what appears to be only one line of source code.

Handling file exceptions

Of course you can generate exceptions when trying to open a file, and if you want to handle your exceptions, you use a syntax similar to the Java try/catch syntax, like this:

import scala.io.Source

val filename = "no-such-file.scala"
try {
  for (line <- Source.fromFile(filename).getLines()) {
    println(line)
  }
} catch {
  case ex: Exception => println("Bummer, an exception happened.")
}

If I change that Exception line to print my exception object, like this:

case ex: Exception => println(ex)

and then run this script again, I can see that this code throws a java.io.FileNotFoundException exception when it fails:

java.io.FileNotFoundException: no-such-file.scala (No such file or directory)

As a result, if I want to catch all the old Java exceptions like I used to, I can write a Scala script like this to catch the Java FileNotFoundException and IOException:

import scala.io.Source
import java.io.{FileReader, FileNotFoundException, IOException}

val filename = "no-such-file.scala"
try {
for (line <- Source.fromFile(filename).getLines()) {
  println(line)
}
} catch {
  case ex: FileNotFoundException => println("Couldn't find that file.")
  case ex: IOException => println("Had an IOException trying to read that file")
}


Posted by 1010
00.scala2014. 3. 28. 15:38
반응형

Scala XML FAQ: How do I load an XML URL in Scala? (How do I read/download the contents of an XML URL in Scala?)

To load the contents of an XML URL (web page) in Scala, such as an RSS news feed or RESTful web service, just use the load method of the Scala XML class:

val xml = XML.load("http://www.devdaily.com/rss.xml")

Here's an example of what this looks like in the Scala REPL:

scala> import scala.xml.XML
import scala.xml.XML

scala> val xml = XML.load("http://www.devdaily.com/rss.xml")
xml: scala.xml.Elem = 
<rss xml:base="http://www.devdaily.com" version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/">
<channel>

(output goes on for about ten more lines)

Once you have your XML object (an instance of the scala.xml.Elem class), you can search it as usual. Since my RSS feed includes an "item" tag, I can get the number of item tags in the XML contents:

scala> (xml \\ "item").length
res5: Int = 10

I can also do things like searching for "title" elements, such as getting the text from the first RSS title element:

scala> val firstTitle = (xml \\ "channel" \ "title") text
firstTitle: String = devdaily.com

As you can see, loading the contents of an XML URL in Scala is very easy.

Posted by 1010
00.scala2014. 3. 28. 15:37
반응형

Scala FAQ: How do I load an XML file in Scala? (How do I open and read an XML file in Scala?)

I demonstrated this in my earlier Scala XML - Searching XMLNS namespaces, XPath tutorial, but you can load an XML file in Scala like this:

import scala.xml.XML
val xml = XML.loadFile("/Users/al/Projects/Scala/yahoo-weather.xml")

Once you've loaded the file contents like that, you can manipulate them as desired, such as searching the XML using XPath constructs like this:

val temp = (xml \\ "channel" \\ "item" \ "condition" \ "@temp") text

In summary, if you need to load an XML file in Scala, I hope this has been helpful.

Posted by 1010
00.scala2014. 3. 28. 15:37
반응형

Problem: You want to write XML data to a file in a Scala application, such as saving application data or configuration information to a file.

Solution

Use the scala.xml.XML.save method to write a Scala literal to a file. Given this XML literal:

// create an XML variable
val portfolio = 
  <portfolio>
    <stocks>
      <stock>AAPL</stock>
      <stock>AMZN</stock>
      <stock>GOOG</stock>
    </stocks>
    <reits>
      <reit>Super REIT 1</reit>
    </reits>
  </portfolio>

write the literal to file with the save method:

// save the XML to a file
scala.xml.XML.save("portfolio.xml", portfolio)

This creates a plain-text file named portfolio.xml in the current directory, containing the XML literal shown.

As with any file-writing code, beware that XML.save can throw an exception:

scala> scala.xml.XML.save("/foo/bar/baz", portfolio)
java.io.FileNotFoundException: /foo/bar/baz (No such file or directory)

Additional save parameters

The save method lets you specify other parameters, including the encoding to use, whether or not to write an XML declaration, and whether or not to write a DOCTYPE declaration.

To write the data to a file with encoding information, use this approach:

XML.save("portfolio.xml", portfolio, "UTF-8", true, null)

This results in the following header being added to the file:

<?xml version='1.0' encoding='UTF-8'?>

To add a DOCTYPE to the file, first import the necessary classes:

import scala.xml.dtd.{DocType, PublicID}

Then create a DocType instance, and save the file with that instance:

val doctype = DocType("html",
  PublicID("-//W3C//DTD XHTML 1.0 Strict//EN",
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"),
  Nil)

XML.save("portfolio.xml", portfolio, "UTF-8", true, doctype)

With this configuration, the following DOCTYPE line is added to the output file:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

The scala.xml package also includes a Utility object with a small collection of useful methods that let you sort node attributes, trim elements, remove comments, and more.

Pretty printing

If it’s important that the XML can be easily read by a human being, it’s best to use the PrettyPrinter class to make sure the XML is “human readable.” But because the PrettyPrinter returns a String, you’ll need to write it to a file using another method. I have my own FileUtils class, so the process looks like this:

val portfolio =
  <portfolio>
    <stocks>
      <stock>AAPL</stock><stock>AMZN</stock><stock>GOOG</stock>
    </stocks>
    <reits><reit>Super REIT 1</reit></reits>
  </portfolio>

// 80 characters wide, 2 character indentation
val prettyPrinter = new scala.xml.PrettyPrinter(80, 2)
val prettyXml = prettyPrinter.format(portfolio)
FileUtils.save("portfolio.xml", prettyXml)


Posted by 1010
00.scala2014. 3. 28. 14:23
반응형

Problem: You want to dynamically generate XML from your Scala source code, such as creating output for a SOAP web service.

Solution

A great feature of Scala’s XML support is that you can interweave XML and regular Scala source code together. This lets you dynamically generate XML from your Scala code.

To create XML with dynamic, embedded data, just put your Scala code in curly braces inside the XML tags, as shown in the following example:

scala> val name = "Bill"
name: String = Bill

scala> val age = 42
age: Int = 42

scala> val p = <person><name>{name}</name><age>{age}</age></person>
p: scala.xml.Elem = <person><name>Bill</name><age>42</age></person>

In this example, the Scala variables name and age are put inside curly braces, inside the XML literals. The variable p in the REPL results shows that they’re translated to their values (Bill and 42, respectively). Methods and other expressions can be used in the same way.

This ability to weave Scala code and XML together is similar to using a templating system, and is a great way to generate dynamic XML output, including output like an RSS news feed, all forms of business data, or a simple XHTML UL/LI tag combination:

scala> val fruits = List("apple", "banana", "orange")
fruits: List[java.lang.String] = List(apple, banana, orange)

scala> val ul = <ul>{fruits.map(i => <li>{i}</li>)}</ul>
ul: scala.xml.Elem = <ul><li>apple</li><li>banana</li><li>orange</li></ul>

scala> println(ul)
<ul><li>apple</li><li>banana</li><li>orange</li></ul>

You can use the same technique to generate XHTML <select> and <option> tags, such as for a list of states or credit cards options, and any other form of XML data.

Discussion

As shown in the fruits example, XML literals can contains Scala code in curly braces, and that code can include additional XML literal values, which can contain Scala code. This nesting of Scala and XML can continue to go deeper, as needed.

To explain how this works, let’s look at the code again:

val ul = <ul>{fruits.map(i => <li>{i}</li>)}</ul>

Here’s how this code works:

  • The XML expression is enclosed in the matching <ul> tags.
  • The curly braces begin the fruits.map Scala expression.
  • <li> tags are embedded in the code block passed to the map method.
  • The variable i is enclosed in curly braces inside the <li> tags, where it will be replaced by its values as the map method executes.

If you’ve used XML/HTML templating tools previously, you can appreciate the power of this approach.

NodeBuffer

The NodeBuffer class provides another nice way to dynamically build XML. The following example shows how to build a set of <li> tags as a NodeBuffer, and then insert those elements into a final <ul>tag:

scala> val x = new xml.NodeBuffer
x: scala.xml.NodeBuffer = ArrayBuffer()

scala> x += <li>apple</li>
res0: x.type = ArrayBuffer(<li>apple</li>)

scala> x += <li>banana</li>
res1: x.type = ArrayBuffer(<li>apple</li>, <li>banana</li>)

scala> val ul = <ul>{x}</ul>
ul: scala.xml.Elem = <ul><li>apple</li><li>banana</li></ul>

NodeBuffer is a simple convenience class that extends ArrayBuffer[Node]. It adds one method named &+that appends the given object to the buffer, and returns a this reference for convenience. This lets you write a “fluent” style of code like this, if you prefer:

val nb = new xml.NodeBuffer
val nb2 = nb &+ <li>apple</li> &+ <li>banana</li> &+ <li>cherry</li>

See Recipe 5.9 of the Scala Cookbook, “Supporting a Fluent Style of Programming,” for more information on supporting and using this coding style.

Posted by 1010
00.scala2014. 3. 28. 13:43
반응형

After writing a Java REST (RESTful) client using Apache HttpClient, I turned around and modified that code to be a Scala REST client, also using the Apache HttpClient library.

Here then, without much introduction, is the source code for a Scala REST client example, which demonstrates how to read information from the Yahoo Weather API, which is actually an RSS feed. As a result, this example also demonstrates how to search an XML document for the information you want, using the built-in Scala XML parsing capabilities.

package tests

import java.io._
import org.apache.http.HttpEntity
import org.apache.http.HttpResponse
import org.apache.http.client.ClientProtocolException
import org.apache.http.client.HttpClient
import org.apache.http.client.methods.HttpGet
import org.apache.http.impl.client.DefaultHttpClient
import scala.collection.mutable.StringBuilder
import scala.xml.XML

object ScalaApacheHttpRestClient {

  def main(args: Array[String]) {
  
    // (1) get the content from the yahoo weather api url
    val content = getRestContent("http://weather.yahooapis.com/forecastrss?p=80020&u=f")
    
    // (2) convert it to xml
    val xml = XML.loadString(content)
    assert(xml.isInstanceOf[scala.xml.Elem])  // needed?

    // (3) search the xml for the nodes i want
    val temp = (xml \\ "channel" \\ "item" \ "condition" \ "@temp") text
    val text = (xml \\ "channel" \\ "item" \ "condition" \ "@text") text

    // (4) print the results
    val currentWeather = format("The current temperature is %s degrees, and the sky is %s.", temp, text.toLowerCase())
    println(currentWeather)
  }
  
  /**
   * Returns the text content from a REST URL. Returns a blank String if there
   * is a problem.
   */
  def getRestContent(url:String): String = {
    val httpClient = new DefaultHttpClient()
    val httpResponse = httpClient.execute(new HttpGet(url))
    val entity = httpResponse.getEntity()
    var content = ""
    if (entity != null) {
      val inputStream = entity.getContent()
      content = io.Source.fromInputStream(inputStream).getLines.mkString
      inputStream.close
    }
    httpClient.getConnectionManager().shutdown()
    return content
  }

}

Description

As you can see from the main method, the code is pretty simple, only involving a few steps. The getRestContent function does a lot of the dirty work involved in getting the content from a REST URL. (That function can probably be written better, as I'm ignoring a number of exceptions that can happen.)

There is also some magic involved in processing the XML using the Scala XML library. It took me longer to figure out the syntax to search the XML for the nodes I wanted than it did to write the rest of this example, so I'll discuss that Scala XML syntax in another tutorial.

As I mentioned in my earlier Java RESTful client example, there are several other good ways of creating REST clients in Java and Scala, including using the Jersey project, or the Apache CXF project. Those libraries are specifically geared more towards web services and implementing the API of the Java JSRs that describe web services, while the Apache HttpClient library just simplifies the process of creating HTTP clients. Which one you use is up to you, and I hope/plan to write RESTful clients in Scala using each of those libraries.

In trying to keep this short, I'll leave the example and discussion at that. As usual, if you have any questions, comments, or improvements, just leave a note in the comments section below.

Posted by 1010
00.scala2014. 3. 28. 13:42
반응형

Scala JDBC FAQ: How can I use the Java JDBC API in my Scala application?

If you want to use a SQL database with your Scala applications, it's good to know you can still use the traditional Java JDBC programming library to access databases. I just ran a simple JDBC connectionand SQL SELECT test, and everything seems to work just as it does in Java.

A Scala, JDBC, and MySQL example

Without any further introduction, here's the source code for a complete Scala class (an object, actually) that connects to a MySQL database using nothing but plain old JDBC. In this example I'm connecting to a MySQL database server on my local computer, and then running a SQL SELECT query against theuser table of the mysql database:

package jdbc

import java.sql.DriverManager
import java.sql.Connection

/**
 * A Scala JDBC connection example by Alvin Alexander,
 * http://alvinalexander.com
 */
object ScalaJdbcConnectSelect {

  def main(args: Array[String]) {
    // connect to the database named "mysql" on the localhost
    val driver = "com.mysql.jdbc.Driver"
    val url = "jdbc:mysql://localhost/mysql"
    val username = "root"
    val password = "root"

    // there's probably a better way to do this
    var connection:Connection = null

    try {
      // make the connection
      Class.forName(driver)
      connection = DriverManager.getConnection(url, username, password)

      // create the statement, and run the select query
      val statement = connection.createStatement()
      val resultSet = statement.executeQuery("SELECT host, user FROM user")
      while ( resultSet.next() ) {
        val host = resultSet.getString("host")
        val user = resultSet.getString("user")
        println("host, user = " + host + ", " + user)
      }
    } catch {
      case e => e.printStackTrace
    }
    connection.close()
  }

}

As you can see, this Scala JDBC database connection example looks just like Java JDBC, which you can verify from my very old JDBC connection example and JDBC SQL SELECT example.

If you're new to JDBC and the MySQL URL shown above looks weird because I'm accessing the "mysql" database in the MySQL database server, remember that the general MySQL connection URL looks like this:

val url = "jdbc:mysql://hostname/database_name"

and if I was instead connecting to a database named drupal7, the MySQL URL would look like this instead:

val url = "jdbc:mysql://localhost/drupal7"


Posted by 1010
00.scala2014. 3. 28. 13:41
반응형

Scala FAQ: Can you share some examples of using tuples in Scala?

Getting started with tuples

A Scala tuple is a class that can contain a miscellaneous collection of elements. I like to think of them as a little bag or container you can use to hold things and pass them around.

You create a tuple with the following syntax, enclosing its elements in parentheses. Here's a tuple that contains an Int and a String:

val stuff = (42, "fish")

This creates a specific instance of a tuple called a Tuple2, which we can demonstrate in the REPL:

scala> val stuff = (42, "fish")
stuff: (Int, java.lang.String) = (42,fish)

scala> stuff.getClass
res0: java.lang.Class[_ <: (Int, java.lang.String)] = class scala.Tuple2

A tuple isn't actually a collection; it's a series of classes named Tuple2Tuple3, etc., through Tuple22. You don't have to worry about that detail, other than knowing that you can have anywhere from two to twenty-two items in a tuple. (And in my opinion, if you have twenty-two miscellaneous items in a bag, you should probably re-think your design.)

Accessing tuple elements

You can access tuple elements using an underscore syntax. The first element is accessed with _1, the second element with _2, and so on, like this:

scala> val things = ("a", 1, 3.5)
things: (java.lang.String, Int, Double) = (a,1,3.5)

scala> println(things._1)
a

scala> println(things._2)
1

scala> println(things._3)
3.5

Use variable names to access tuple elements

When referring to a Scala tuple you can also assign names to the elements in the tuple. I like to do this when returning miscellaneous elements from a method. To demonstrate the syntax, let's create a very simple method that returns a tuple:

def getUserInfo = ("Al", 42, 200.0)

Now we can call that method, and assign the tuple results directly to variables, like this:

val(name, age, weight) = getUserInfo

Here's what this looks like in the REPL:

scala> def getUserInfo = ("Al", 42, 200.0)
getUserInfo: (java.lang.String, Int, Double)

scala> val(name, age, weight) = getUserInfo
name: java.lang.String = Al
age: Int = 42
weight: Double = 200.0

It's shown in the REPL results, but we'll further confirm that we can indeed access the values by variable name:

scala> name
res4: java.lang.String = Al

scala> age
res5: Int = 42

scala> weight
res6: Double = 200.0

That's pretty nice.

In a cool, related feature, if you only want to access some of the elements, you can ignore the others by using an underscore placeholder for the elements you want to ignore. Imagine you want to ignore theweight in our example:

scala> val(name, age, _) = getUserInfo
name: java.lang.String = Al
age: Int = 42

Or suppose you want to ignore the age and weight:

scala> val(name, _, _) = getUserInfo
name: java.lang.String = Al

Again, that's good stuff.

Iterating over a Scala tuple

As mentioned, a tuple is not a collection; it doesn't descend from any of the collection traits or classes. However, you can treat it a little bit like a collection by using its productIterator method.

Here's how you can iterate over the elements in a tuple:

scala> val t = ("Al", 42, 200.0)
t: (java.lang.String, Int, Double) = (Al,42,200.0)

scala> t.productIterator.foreach(println)
Al
42
200.0

The tuple toString method

The tuple toString method gives you a nice representation of a tuple:

scala> t.toString
res9: java.lang.String = (Al,42,200.0)

scala> println(t.toString)
(Al,42,200.0)

Creating a tuple with ->

In another cool feature, you can create a tuple using this syntax:

1 -> "a"

This creates a Tuple2, which we can demonstrate in the REPL:

scala> 1 -> "a"
res1: (Int, java.lang.String) = (1,a)

scala> res11.getClass
res2: java.lang.Class[_ <: (Int, java.lang.String)] = class scala.Tuple2

You'll see this syntax a lot when creating maps:

scala> val map = Map(1->"a", 2->"b")
map: scala.collection.immutable.Map[Int,java.lang.String] = Map(1 -> a, 2 -> b)


Posted by 1010
00.scala2014. 3. 28. 13:41
반응형

Scala Map FAQ: How can I iterate/loop over a Scala Map?

There are several different ways to iterate over a Scala Map, and the method you choose depends on the problem you need to solve.

To get started with our examples, let's create a simple Map we can work with:

scala> val m1 = Map("fname" -> "Al", "lname" -> "Alexander")

Iterating over Scala maps

Once you have a Map, you can iterate over it using several different techniques. For me, this is by far the easiest technique:

scala> for ((k,v) <- m1) printf("key: %s, value: %s\n", k, v)
key: fname, value: Al
key: lname, value: Alexander

This page has some other Map and for loop examples, which I've reproduced here:

// version 1 (tuples)
m1 foreach (x => println (x._1 + "-->" + x._2))

// version 2 (foreach and case)
m1 foreach {case (key, value) => println (key + "-->" + value)}

You can choose whatever format you prefer. Scala is beginning to remind me of the Perl slogan: "There's more than one way to do it", and this is good, because you can choose whichever approach makes the most sense for the problem at hand.

Scala Map, keys, foreach, and tuples

To demonstrate a more "real world" example of looping over a Scala Map, while working through some programming examples in the book, Programming Collective Intelligence, I decided to code them up in Scala, and I wanted to share the approaches I prefer using the Scala foreach and for loops.

To begin with, I defined my Scala Map like this:

val p1Ratings = Map("Lady in the Water"-> 3.0, 
                    "Snakes on a Plane"-> 4.0,
                    "You, Me and Dupree"-> 3.5)

In my case, when I'm iterating over the Map I'm really just interested in the Map keys, so the cleanest way to loop over every Map element is like this:

p1Ratings.keys.foreach( (movie) => 
  if (p2Ratings.contains(movie)) similarItems += (movie -> true)
)

While I chose that looping method in my code, I could also use the "tuples" approach, where movie is a Tuple, and I only use the first element of the Tuple, which happens to be my keys:

p1Ratings foreach ( (movie) => 
  if (p2Ratings.contains(movie._1)) similarItems += (movie._1 -> true)
)

In that approach, I ignore the second element of each Tuple, because I don't need it. (Which is why I don't like this approach for this instance.)

In a similar approach, I loop over the Map as shown next, creating a field named rating1 which I again don't use because I don't need it:

for ((movie1, rating1) <- p1Ratings) {
  if (p2Ratings.contains(movie1)) similarItems += (movie1 -> true)
}

These last two approaches will work better, and look a little more logical, if you need to access the key and value for each map element, but in my case, since I don't need to values, I'm using the first approach shown above.

Posted by 1010
00.scala2014. 3. 28. 13:40
반응형

Here's a quick look at how to use the Scala Map class, with a colllection of Map class examples.

The immutable Map class is in scope by default, so you can create an immutable map without an import, like this:

val states = Map("AL" -> "Alabama", "AK" -> "Alaska")

To create a mutable Map, import it first:

var states = scala.collection.mutable.Map("AL" -> "Alabama")

Adding, removing, and updating mutable Map elements

The following examples show how to add, remove, and update elements in a mutable Scala Map:

// create an empty map
var states = scala.collection.mutable.Map[String, String]()

// create a map with initial elements
var states = scala.collection.mutable.Map("AL" -> "Alabama", "AK" -> "Alaska")

// add elements with +=
states += ("AZ" -> "Arizona")
states += ("CO" -> "Colorado", "KY" -> "Kentucky")

// remove elements with -=
states -= "KY"
states -= ("AZ", "CO")

// update elements by reassigning them
states("AK") = "Alaska, The Big State"

Iterating over Scala maps

Once you have a Map, you can iterate over it using several different techniques. I prefer using the for loop (or for comprehension):

scala> val m1 = Map("fname" -> "Al", "lname" -> "Alexander")

scala> for ((k,v) <- m1) printf("key: %s, value: %s\n", k, v)
key: fname, value: Al
key: lname, value: Alexander

This page has some other Map and for loop examples, which I've reproduced here:

// version 1 (tuples)
m1 foreach (x => println (x._1 + "-->" + x._2))

// version 2 (foreach and case)
m1 foreach {case (key, value) => println (key + "-->" + value)}

You can choose whatever format you prefer.

A few more ways to iterate over a Scala Map

To demonstrate a more "real world" example of looping over a Scala Map, while I was working through some programming examples in the book, Programming Collective Intelligence, I decided to code them up in Scala.

To begin with, I defined my Scala Map like this:

val p1Ratings = Map("Lady in the Water"-> 3.0, 
                    "Snakes on a Plane"-> 4.0,
                    "You, Me and Dupree"-> 3.5)

In my case, when I'm iterating over the Map I'm really just interested in the Map keys, so the cleanest way to loop over every Map element is like this:

p1Ratings.keys.foreach( (movie) => 
  if (p2Ratings.contains(movie)) similarItems += (movie -> true)
)

While I chose that looping method in my code, I could also use the "tuples" approach, where movie is a Tuple, and I only use the first element of the Tuple, which happens to be my keys:

p1Ratings foreach ( (movie) => 
  if (p2Ratings.contains(movie._1)) similarItems += (movie._1 -> true)
)

In that approach, I ignore the second element of each Tuple, because I don't need it. (Which is why I don't like this approach for this instance.)

In a similar approach, I loop over the Map as shown next, creating a field named rating1 which I again don't use because I don't need it:

for ((movie1, rating1) <- p1Ratings) {
  if (p2Ratings.contains(movie1)) similarItems += (movie1 -> true)
}

These last two approaches will work better, and look a little more logical, if you need to access the key and value for each map element, but in my case, since I don't need to values, I'm using the first approach shown above.

Posted by 1010
00.scala2014. 3. 28. 13:40
반응형

The Scala List class filter method implicitly loops over the List you supply, tests each element of the List with the function you supply. Your function must return true or false, and filter returns the list elements where your function returns true.

(Note: Even though I use a List in these examples, the filter method can be used on any Scala sequence, including Array, List, Vector, Seq, etc.)

Let's look at a few simple examples. In this first example we filter a small list of numbers so that our resulting list only has numbers that are greater than 2:

scala> val nums = List(5, 1, 4, 3, 2)
nums: List[Int] = List(5, 1, 4, 3, 2)

scala> nums.filter(_ > 2)
res0: List[Int] = List(5, 4, 3)

Note that in the real world you'd assign the filtered results to a new List, like this:

val originalList = List(5, 1, 4, 3, 2)
val newList = originalList.filter(_ > 2)

This example shows how to get the even numbers from a List using a simple modulus test:

scala> nums.filter( _ % 2 == 0 )
res21: List[Int] = List(4, 2)

You can take that example a step further by filtering and then sorting the list:

# filter and sort
scala> nums.filter( _ % 2 == 0 ).sort(_ < _)
warning: there were 1 deprecation warnings; re-run with -deprecation for details
res22: List[Int] = List(2, 4)

filter method examples with a List of Strings

Here are two filter method examples with a list of Strings:

val fruits = List("orange", "peach", "apple", "banana")

scala> fruits.filter(_.length > 5)
res21: List[java.lang.String] = List(banana, orange)

scala> fruits.filter(_.startsWith("a"))
res22: List[java.lang.String] = List(apple)

Combining filter, sort, and map

From the excellent book, Beginning Scala, here's a nice combination of the List filter, sort, and map methods:

trait Person {
  def first: String
  def age: Int
  def valid: Boolean
}

Returns the first name of 'valid' persons, sorted by age

def validByAge(in: List[Person]) =
  in.filter(_.valid).
  sort(_.age < _.age).
  map(_.first)

The following example shows how you can use filter with map to transform the type of data that the expression returns. In this case we'll start with a sequence of Person objects, and transform it into a sequence of String objects.

We'll start with a simple case class:

scala> case class Person(first: String, last: String, mi: String)
defined class Person

Next, we'll create a little sequence of Person objects:

scala> val fred = Person("Fred", "Flintstone", "J")
fred: Person = Person(Fred,Flintstone,J)

scala> val wilma = Person("Wilma", "Flintstone", "A")
wilma: Person = Person(Wilma,Flintstone,A)

scala> val barney = Person("Barney", "Rubble", "J")
barney: Person = Person(Barney,Rubble,J)

scala> val betty = Person("Betty", "Rubble", "A")
betty: Person = Person(Betty,Rubble,A)

scala> val peeps = Seq(fred, wilma, barney, betty)
peeps: Seq[Person] = List(Person(Fred,Flintstone,J), Person(Wilma,Flintstone,A), Person(Barney,Rubble,J), Person(Betty,Rubble,A))

Finally, we'll combine filter and map to get a list of all first names where the last name is "Flintstone":

scala> peeps.filter(_.last == "Flintstone").map(_.first)
res0: Seq[String] = List(Fred, Wilma)

The way this works is:

  • The filter method returns a sequence of Person objects where the last name is "Flintstone".
  • The map method call gets the first name of each Person object. This results in a sequence of strings, where each string is the first name of each person that came out of the filter call.

I initially wrote this as a for/yield loop, but then realized I could write this much more concisely with this approach. At the moment I find the for/yield loop to be more readable, and this to be much more concise.

In my opinion, this code can be made a little more readable by using a variable name in the mapexpression, as a reminder that you're still dealing with Person objects:

scala> peeps.filter(_.last == "Flintstone").map(person => person.first)
res1: Seq[String] = List(Fred, Wilma)

Scala List filter method summary

I hope these filter method examples have been helpful. Here's a quick summary of how the filter method works:

  • filter implicitly loops over a List.
  • filter takes a function as an argument. That function should take one List element as input, perform the test you define, and then return either true or false (a Boolean).
  • filter only returns List elements that match the filtering expression.


Posted by 1010
00.scala2014. 3. 28. 13:39
반응형

Scala List FAQ: Can you share some Scala List class examples?

The Scala List class may be the most commonly used data structure in Scala applications. Therefore, it's very helpful to know how create lists, merge lists, select items from lists, operate on each element in a list, and so on.

In this tutorial, I'll try to share examples of the most common List operations (methods).

Scala List class - Introduction

The Scala List class (scala.List) holds a sequenced, linear list of items. In a List, each element must be of the same type.

At some point I'll add a class diagram here, but until then, here's a simplified version of the Scala List class hierarchy:

  • The scala.List class is a pointer to the scala.collection.immutable.List class.
  • The List class extends LinearSeq with Product (and some others).
  • The trait LinearSeq extends Seq
  • The trait Seq extends Iterable
  • Iterable extends trait Traversable

(I need to update this, but this is the Scala class hierarchy, as shown by the current Scala API documentation.

Creating a Scala List object

You can create a Scala List object in several different way. Here's the Lisp-style approach to creating a List:

scala> val list = 1 :: 2 :: 3 :: Nil
list: List[Int] = List(1, 2, 3)

Here's the Java-style approach to creating a Scala List:

scala> val list = List(1,2,3)
x: List[Int] = List(1, 2, 3)

A few notes about these approaches:

  • The first approach shows the "cons" syntax, which, as I mentioned, is the Lisp style of creating a list.
  • The :: method takes two arguments, a "head", which is a single element, and a "tail", which is a List.
  • As you can see, Scala can usually infer the type of a List very well.

If you're mixing types in a List constructor, you may need to manually specify the List type. This example demonstrates that syntax:

scala> val x = List[Number](1, 2.0, 33d, 0x1)
x: List[java.lang.Number] = List(1, 2.0, 33.0, 1)

In this example, I'm explicitly saying that I want the values in the List to be saved as the Number type.

The List range method

You can also create a List with the List's range method:

scala> val x = List.range(1,10)
x: List[Int] = List(1, 2, 3, 4, 5, 6, 7, 8, 9)

The range function can also take a third argument which serves as a "step" value when creating the List:

scala> val x = List.range(0,10,2)
x: List[Int] = List(0, 2, 4, 6, 8)

The List fill method

You can also create a new List with the fill method:

scala> val x = List.fill(3)("foo")
x: List[java.lang.String] = List(foo, foo, foo)

The List tabulate method

Finally, you can create a new List with the tabulate method of the List class. The tabulate method creates a new List whose elements are created according to the function you supply. The book Programming in Scala shows how to create a List using a simple "squares" function:

scala> val x = List.tabulate(5)(n => n * n)
x: List[Int] = List(0, 1, 4, 9, 16)

As you can see, that example creates a List of five elements, where the element values are the square of the index of each element (0 becomes 0, 1 becomes 1, 2 becomes 4, 3 becomes 9, and 4 becomes 16).

In summary, you can create a new Scala List with these approaches:

  • Lisp style
  • Java style
  • range method
  • tabulate method

Prepend items to a List

You can prepend items to a Scala List using the :: method:

// create a List
scala> val x = List(1,2,3)
x: List[Int] = List(1, 2, 3)

// prepend an element to the list
scala> val y = 0 :: x
y: List[Int] = List(0, 1, 2, 3)

According to the Beginning Scala book (and several other sources), prepending items to a list is a "very fast, constant-time, O(1) operation."

(Again, I recall this approach and syntax from using Lisp many years ago.)

Appending and merging Lists

There are at least two ways to merge Scala Lists. First, you can merge two Scala lists using the ::: method of the List class:

scala> val a = List(1,2,3)
a: List[Int] = List(1, 2, 3)

scala> val b = List(4,5,6)
b: List[Int] = List(4, 5, 6)

scala> val c = a ::: b
c: List[Int] = List(1, 2, 3, 4, 5, 6)

This operation is said to have O(n) speed, where n is the number of elements in the first List.

You can also merge two Scala lists using the List's concat method:

scala> val a = List(1,2,3)
a: List[Int] = List(1, 2, 3)

scala> val b = List(4,5,6)
b: List[Int] = List(4, 5, 6)

scala> val c = List.concat(a, b)
c: List[Int] = List(1, 2, 3, 4, 5, 6)

Iterating lists with foreach

A very common way to iterate over Scala lists is with the foreach method. Here's a quote about the foreach method from the book Programming in Scala:

foreach takes a procedure (a function with a result type Unit) as the right operand. It simply applies the procedure to each List element. The result of the operation is again Unit; no list of results is assembled.

Here's a simple example showing how to use the foreach function to print every item in a List:

scala> val x = List(1,2,3)
x: List[Int] = List(1, 2, 3)

scala> x.foreach { println }
1
2
3

This next example shows a way to sum all the elements in a list using the foreach method:

scala> var sum = 0
sum: Int = 0

scala> val x = List(1,2,3)
x: List[Int] = List(1, 2, 3)

scala> x.foreach(sum += _)

scala> println(sum)
6

Scala Lists and the for comprehension

The Scala for comprehension is not specific to lists, but is an extremely powerful way to operate on lists. Here's a simple example of how to iterate over a list using the for comprehension:

scala> val names = List("Bob", "Fred", "Joe", "Julia", "Kim")
names: List[java.lang.String] = List(Bob, Fred, Joe, Julia, Kim)

scala> for (name <- names) println(name)
Bob
Fred
Joe
Julia
Kim

So far, so good. Now let's add a simple "if" clause to the for comprehension to print only the elements we want to print:

scala> val names = List("Bob", "Fred", "Joe", "Julia", "Kim")
names: List[java.lang.String] = List(Bob, Fred, Joe, Julia, Kim)

scala> for (name <- names if name.startsWith("J"))
     | println(name)
Joe
Julia

If you already know about the for comprehension, you know that you can add multiple if clauses, and much more functionality. I could easily write an entire tutorial on the Scala for comprehension, so to keep this tutorial short, I'll stop here for now.

Before leaving, I will add these notes however, from the book Programming in Scala:

Scala provides the for comprehension, which provides syntactically pleasing nesting of map, flatMap, and filter ... The for comprehension is not a looping construct, but is a syntactic construct the compiler reduces to map, flatMap, and filter.

Filtering Scala lists

A great thing about Scala is that it is a functional programming language. In the next examples we'll show some of the power of functional programming. In this section we'll focus on the filter method of the List class.

scala> val x = List(1,2,3,4,5,6,7,8,9,10)
x: List[Int] = List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)

// create a list of all the even numbers in the list
scala> val evens = x.filter(a => a % 2 == 0)
evens: List[Int] = List(2, 4, 6, 8, 10)

takeWhile

scala> val x = List(1,2,3,4,5,6,7,8,9,10)
x: List[Int] = List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)

scala> val y = x.takeWhile(a => a < 6)
y: List[Int] = List(1, 2, 3, 4, 5)

Other list filtering methods:

partition - returns a pair of lists, one where the predicate is true,
            the other where the predicate is false
find      - returns the first element matching a predicate (as opposed to
            returning all such elements)

Others:   takeWhile, dropWhile, span

The List map function

The Scala List map function "transforms each element of a collection based on a function."

Here are a few map examples. First, doubling every item in a List:

scala> val x = List(1,2,3)
x: List[Int] = List(1, 2, 3)

scala> val y = x.map(a => a * 2)
y: List[Int] = List(2, 4, 6)

Here's a slightly simpler version of that map example, using the Scala wildcard character (_) instead of a fake variable name:

scala> val y = x.map(_ * 2)
y: List[Int] = List(2, 4, 6)

Here's an example using a list of strings:

scala> val names = List("Fred", "Joe", "Bob")
names: List[java.lang.String] = List(Fred, Joe, Bob)

scala> val lower = names.map(_.toLowerCase)
lower: List[java.lang.String] = List(fred, joe, bob)

scala> val upper = names.map(_.toUpperCase)
upper: List[java.lang.String] = List(FRED, JOE, BOB)

A very nice example in the book Beginning Scala demonstrates how to convert a List into something useful in the HTML world, a list of <li> elements using the map function:

scala> val names = List("Fred", "Joe", "Bob")
names: List[java.lang.String] = List(Fred, Joe, Bob)

scala> val li = names.map(name => <li>{name}</li>)
li: List[scala.xml.Elem] = List(<li>Fred</li>, <li>Joe</li>, <li>Bob</li>)

As you can see, you can rapidly build a lot of functionality in just a little bit of code.

Sorting Scala Lists

I need to research why this code is deprecated, but for the time being, here's an example of how to sort a Scala List:

scala> val x = List(10, 2, 5)
x: List[Int] = List(10, 2, 5)

scala> val y = x.sort(_ < _)
warning: there were 1 deprecation warnings; re-run with -deprecation for details
y: List[Int] = List(2, 5, 10)

(TODO: Research the correct, current approach for sorting Scala lists.)

Scala List class and pattern matching

You can use the List class with the Scala pattern matching and case/match syntax. I'll add examples here as I create them in my own code. (TODO)

Other Scala List functions

The Scala List class has an incredible number of functions/methods, and over time I'll attempt to document them all. In the meantime, here's a short list of the many other Scala List methods I don't have examples for at this time:

length  - returns the length of a List
head    - returns the first element of a List
last    - returns the last element of a List
init    - returns a List consisting of all elements except the last one
tail    - returns every elements of a List except the first element
isEmpty - returns a Boolean indicating if the List is empty

reverse - returns a reversed version of the List
flatten - takes a list of lists and flattens it out to a single list

mkString - converts a List to a String

iterator
toArray

foldLeft
reduceLeft

map
flatMap
foreach

forall
exists

Folding lists: /: and :\

sortWith

Again, I'll try to add examples of these List methods over time. (TODO)

Relatives of the Scala List

There are times you may want to use one of the relatives of the Scala List class, instead of using the List class itself. I'll add more to this over time, but for now, here are a few links:


Posted by 1010
00.scala2014. 3. 28. 13:38
반응형

Scala List class FAQ: How do I create a List inScala?

You can create a Scala List in several different ways, including these approaches:

  • Lisp style
  • Java style
  • Using the List class range method
  • Using the List class fill method
  • Using the List class tabulate method

In this Scala List tutorial, I'll demonstrate each of these approaches. I'll execute each command in the Scala command-line interpreter so you can see the results of each approach.

Create a Scala List in the Lisp style

First, if you prefer the Lisp-style of programming, you can create a Scala List using the "cons" syntax, like this:

scala> val list = 1 :: 2 :: 3 :: Nil
list: List[Int] = List(1, 2, 3)

As you can see, this creates a List that contains the Ints 1, 2, and 3. With this approach, you need to end the list with the Nil object.

In this "cons" style, the :: method takes two arguments, a "head", which is a single element, and a "tail", which is a List. (And yes, "::" is a function/method.)

Create a Scala List in the Java style

My guess is that the most popular way to create a List is with what I call the "Java style":

scala> val list = List(1,2,3)
x: List[Int] = List(1, 2, 3)

This syntax looks a lot like the Java way to create an object, except (a) you don't need the "new" keyword before the List, and (b) you don't have to declare the type of elements in the List.

Note that if you're going to mix types in a List constructor, you may need to manually specify the type of the List. This example demonstrates the syntax to specify the List type:

scala> val x = List[Number](1, 2.0, 33d, 0x1)
x: List[java.lang.Number] = List(1, 2.0, 33.0, 1)

In this example I've explicitly stated that the values in the List are of the Number type.

Create a Scala List with the range method

Another convenient way to create a List is with the List class range method:

scala> val x = List.range(1, 10)
x: List[Int] = List(1, 2, 3, 4, 5, 6, 7, 8, 9)

As you can see, this example created a List of Int values, beginning at 1, and ending at 9.

In addition to this simple approach, the range function can also take a third argument, which serves as a "step" value when creating the List:

scala> val x = List.range(0, 10, 2)
x: List[Int] = List(0, 2, 4, 6, 8)

Create a Scala List with the List class fill method

Another convenient way to create a Scala List is with the List class fill method:

scala> val x = List.fill(3)("foo")
x: List[java.lang.String] = List(foo, foo, foo)

As you can see, you just specify how many items you want, and the object value you want to fill each List element with.

Create a Scala List with the List class tabulate method

Finally, you can create a Scala List with the tabulate method of the List class.

The tabulate method creates a new List whose elements are created according to the function you supply. The excellent book "Programming in Scala" shows how to create a List using a simple "squares" function with the tabulate method:

scala> val x = List.tabulate(5)(n => n * n)
x: List[Int] = List(0, 1, 4, 9, 16)

As you can see, that example creates a List of five elements, where the element values are the square of the index of each element, so 0 becomes 0, 1 becomes 1, 2 becomes 4, 3 becomes 9, and 4 becomes 16.

Creating Scala Lists - Summary

In summary, as you have seen, you can create Scala lists in several different ways, including these approaches:

  • Lisp style
  • Java style
  • Using the List class range method
  • Using the List class fill method
  • Using the List class tabulate method

I hope this Scala List class tutorial has been helpful.

Posted by 1010
00.scala2014. 3. 28. 13:37
반응형

Scala List FAQ: How do I merge Scala Lists?

There are at least three ways to merge/concatenate Scala List instances, as shown in the examples below.

1) The Scala List ::: method

First, you can merge two Scala lists using the ::: method of the List class, as demonstrated here at theScala command prompt:

scala> val a = List(1,2,3)
a: List[Int] = List(1, 2, 3)

scala> val b = List(4,5,6)
b: List[Int] = List(4, 5, 6)

scala> val c = a ::: b
c: List[Int] = List(1, 2, 3, 4, 5, 6)

This operation is said to have O(n) speed, where n is the number of elements in the first List.

2) The Scala List concat method

You can also merge two Scala lists using the List class concat method:

scala> val a = List(1,2,3)
a: List[Int] = List(1, 2, 3)

scala> val b = List(4,5,6)
b: List[Int] = List(4, 5, 6)

scala> val c = List.concat(a, b)
c: List[Int] = List(1, 2, 3, 4, 5, 6)

3) The Scala List ++ method

You can also use the List ++ method to concatenate Scala Lists, as shown here:

scala> val a = List(1,2,3)
a: List[Int] = List(1, 2, 3)

scala> val b = List(4,5,6)
b: List[Int] = List(4, 5, 6)

scala> val c = a ++ b
c: List[Int] = List(1, 2, 3, 4, 5, 6)

I'll try to add more information on these three approaches as I learn about them, but for now, I just wanted to share these three approaches.

Posted by 1010
00.scala2014. 3. 28. 13:37
반응형

Scala List/foreach FAQ: How do I iterate over a Scala List using the foreach method and for loop?

There are a number of ways to iterate over a Scala List using the foreach operator and for comprehension, and I'll show a few of those approaches here.

Iterating lists with foreach

A common way to iterate over a Scala List is with the foreach method. Here's a quote about the foreach method from the book Programming in Scala:

foreach takes a procedure (a function with a result type Unit) as the right operand. It simply applies the procedure to each List element. The result of the operation is again Unit; no list of results is assembled.

Here's a simple example showing how to use the foreach function to print every item in a List:

scala> val x = List(1,2,3)
x: List[Int] = List(1, 2, 3)

scala> x.foreach { println }
1
2
3

If you've used a programming language like Ruby, this syntax will look very familiar to you.

This next example shows a way to sum all the elements in a list using the foreach method:

scala> var sum = 0
sum: Int = 0

scala> val x = List(1,2,3)
x: List[Int] = List(1, 2, 3)

scala> x.foreach(sum += _)

scala> println(sum)
6

Scala Lists and the for comprehension

The Scala for comprehension is not specific to lists, but is an extremely powerful way to operate on lists. Here's a simple example of how to iterate over a list using the for comprehension:

scala> val names = List("Bob", "Fred", "Joe", "Julia", "Kim")
names: List[java.lang.String] = List(Bob, Fred, Joe, Julia, Kim)

scala> for (name <- names) println(name)
Bob
Fred
Joe
Julia
Kim

So far, so good. Now let's add a simple "if" clause to the for comprehension to print only the elements we want to print:

scala> val names = List("Bob", "Fred", "Joe", "Julia", "Kim")
names: List[java.lang.String] = List(Bob, Fred, Joe, Julia, Kim)

scala> for (name <- names if name.startsWith("J"))
     | println(name)
Joe
Julia

If you already know about the for comprehension, you know that you can add multiple if clauses, and much more functionality. I could easily write an entire tutorial on the Scala for comprehension, so to keep this tutorial short, I'll stop here for now.

Before leaving, I will add these notes however, from the book Programming in Scala:

Scala provides the for comprehension, which provides syntactically pleasing nesting of map, flatMap, and filter ... The for comprehension is not a looping construct, but is a syntactic construct the compiler reduces to map, flatMap, and filter.


Posted by 1010
00.scala2014. 3. 28. 13:36
반응형

Scala collections FAQ: How can I convert a Scala array to a String?

A simple way to convert a Scala array to a String is with the mkString method of the Array class. (Although I've written "array", the same technique also works with any Scala sequence, including Array, List, Seq, ArrayBuffer, Vector, and other sequence types.)

Here's a quick array to string example using the Scala REPL:

scala> val args = Array("Hello", "world", "it's", "me")
args: Array[java.lang.String] = Array(Hello, world, it's, me)

scala> val string = args.mkString(" ")
string: String = Hello world it's me

In this first statement:

val args = Array("Hello", "world", "it's", "me")

I create a Scala array named args, and in this second statement:

val string = args.mkString(" ")

I create a new String variable named string, separating each String in the array with a space character, which I specified when calling the mkString function.

Using other separator strings

Note that I could have given the mkString function any String to use as a separating character, like this:

scala> val string = args.mkString("\n")
string: String = 
Hello
world
it's
me

or like this:

scala> val string = args.mkString(" . ")
string: String = Hello . world . it's . me

Converting a Scala Int array to a String

As a final example, you can also use the Scala mkString method to convert an Int array to a String, like this:

scala> val numbers = Array(1,2,3)
numbers: Array[Int] = Array(1, 2, 3)

scala> val string = numbers.mkString(", ")
string: String = 1, 2, 3

In summary, I hope these Scala "Array to String" examples have been helpful.


Posted by 1010
00.scala2014. 3. 28. 13:36
반응형

Scala Map FAQ: How can I iterate/loop over a Scala Map?

There are several different ways to iterate over a Scala Map, and the method you choose depends on the problem you need to solve.

To get started with our examples, let's create a simple Map we can work with:

scala> val m1 = Map("fname" -> "Al", "lname" -> "Alexander")

Iterating over Scala maps

Once you have a Map, you can iterate over it using several different techniques. For me, this is by far the easiest technique:

scala> for ((k,v) <- m1) printf("key: %s, value: %s\n", k, v)
key: fname, value: Al
key: lname, value: Alexander

This page has some other Map and for loop examples, which I've reproduced here:

// version 1 (tuples)
m1 foreach (x => println (x._1 + "-->" + x._2))

// version 2 (foreach and case)
m1 foreach {case (key, value) => println (key + "-->" + value)}

You can choose whatever format you prefer. Scala is beginning to remind me of the Perl slogan: "There's more than one way to do it", and this is good, because you can choose whichever approach makes the most sense for the problem at hand.

Scala Map, keys, foreach, and tuples

To demonstrate a more "real world" example of looping over a Scala Map, while working through some programming examples in the book, Programming Collective Intelligence, I decided to code them up in Scala, and I wanted to share the approaches I prefer using the Scala foreach and for loops.

To begin with, I defined my Scala Map like this:

val p1Ratings = Map("Lady in the Water"-> 3.0, 
                    "Snakes on a Plane"-> 4.0,
                    "You, Me and Dupree"-> 3.5)

In my case, when I'm iterating over the Map I'm really just interested in the Map keys, so the cleanest way to loop over every Map element is like this:

p1Ratings.keys.foreach( (movie) => 
  if (p2Ratings.contains(movie)) similarItems += (movie -> true)
)

While I chose that looping method in my code, I could also use the "tuples" approach, where movie is a Tuple, and I only use the first element of the Tuple, which happens to be my keys:

p1Ratings foreach ( (movie) => 
  if (p2Ratings.contains(movie._1)) similarItems += (movie._1 -> true)
)

In that approach, I ignore the second element of each Tuple, because I don't need it. (Which is why I don't like this approach for this instance.)

In a similar approach, I loop over the Map as shown next, creating a field named rating1 which I again don't use because I don't need it:

for ((movie1, rating1) <- p1Ratings) {
  if (p2Ratings.contains(movie1)) similarItems += (movie1 -> true)
}

These last two approaches will work better, and look a little more logical, if you need to access the key and value for each map element, but in my case, since I don't need to values, I'm using the first approach shown above.

Posted by 1010
00.scala2014. 3. 28. 13:35
반응형

Scala List/foreach FAQ: How do I iterate over a Scala List using the foreach method and for loop?

There are a number of ways to iterate over a Scala List using the foreach operator and for comprehension, and I'll show a few of those approaches here.

Iterating lists with foreach

A common way to iterate over a Scala List is with the foreach method. Here's a quote about the foreach method from the book Programming in Scala:

foreach takes a procedure (a function with a result type Unit) as the right operand. It simply applies the procedure to each List element. The result of the operation is again Unit; no list of results is assembled.

Here's a simple example showing how to use the foreach function to print every item in a List:

scala> val x = List(1,2,3)
x: List[Int] = List(1, 2, 3)

scala> x.foreach { println }
1
2
3

If you've used a programming language like Ruby, this syntax will look very familiar to you.

This next example shows a way to sum all the elements in a list using the foreach method:

scala> var sum = 0
sum: Int = 0

scala> val x = List(1,2,3)
x: List[Int] = List(1, 2, 3)

scala> x.foreach(sum += _)

scala> println(sum)
6

Scala Lists and the for comprehension

The Scala for comprehension is not specific to lists, but is an extremely powerful way to operate on lists. Here's a simple example of how to iterate over a list using the for comprehension:

scala> val names = List("Bob", "Fred", "Joe", "Julia", "Kim")
names: List[java.lang.String] = List(Bob, Fred, Joe, Julia, Kim)

scala> for (name <- names) println(name)
Bob
Fred
Joe
Julia
Kim

So far, so good. Now let's add a simple "if" clause to the for comprehension to print only the elements we want to print:

scala> val names = List("Bob", "Fred", "Joe", "Julia", "Kim")
names: List[java.lang.String] = List(Bob, Fred, Joe, Julia, Kim)

scala> for (name <- names if name.startsWith("J"))
     | println(name)
Joe
Julia

If you already know about the for comprehension, you know that you can add multiple if clauses, and much more functionality. I could easily write an entire tutorial on the Scala for comprehension, so to keep this tutorial short, I'll stop here for now.

Posted by 1010
00.scala2014. 3. 28. 13:34
반응형

Here's a quick look at how to create a multi-dimensional array in Scala, in this case a 2D array (matrix), and then access the array elements. As you can see, these commands were issued using the Scala REPL, and I've added a few comments to them:

// create a 2D array
scala> val matrix = Array.ofDim[Int](2,2)
matrix: Array[Array[Int]] = Array(Array(0, 0), Array(0, 0))

// populate the array elements
scala> matrix(0)(0) = 0

scala> matrix(0)(1) = 1

scala> matrix(1)(0) = 2

scala> matrix(1)(1) = 3

// access a couple of array elements
scala> matrix(0)(1)
res4: Int = 1

scala> matrix(1)(0)
res5: Int = 2

If you ever need to create a multidimensional array in Scala, I hope this example is helpful.

Posted by 1010