https를 아직 이해를 못해서.....-_-
일단 기록용으로-_-













[code]
public class Test extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
       
        StringBuilder content = new StringBuilder();
       
        try
        {
            String data = "userid=???&password=???";
            URL url = new URL("https://url~~");
           
            HttpURLConnection http = null;
           
            if (url.getProtocol().toLowerCase().equals("https")) {
                trustAllHosts();
                HttpsURLConnection https = (HttpsURLConnection) url.openConnection();
                https.setHostnameVerifier(DO_NOT_VERIFY);
                http = https;
            } else {
                http = (HttpURLConnection) url.openConnection();
            }
            http.setDoOutput(true);
            OutputStreamWriter wr = new OutputStreamWriter(http.getOutputStream());
            wr.write(data);
            wr.flush();
           
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(http.getInputStream()));

            String line;

            while ((line = bufferedReader.readLine()) != null)
            {
              content.append(line + "\n");
            }
            Log.i("content", content.toString());
            wr.close();
            bufferedReader.close();
        }
        catch(Exception e)
        {
        }
    }
   
    private static void trustAllHosts() {
        // Create a trust manager that does not validate certificate chains
        TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
                public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                        return new java.security.cert.X509Certificate[] {};
                }

                @Override
                public void checkClientTrusted(
                        java.security.cert.X509Certificate[] chain,
                        String authType)
                        throws java.security.cert.CertificateException {
                    // TODO Auto-generated method stub
                   
                }

                @Override
                public void checkServerTrusted(
                        java.security.cert.X509Certificate[] chain,
                        String authType)
                        throws java.security.cert.CertificateException {
                    // TODO Auto-generated method stub
                   
                }
        } };

        // Install the all-trusting trust manager
        try {
                SSLContext sc = SSLContext.getInstance("TLS");
                sc.init(null, trustAllCerts, new java.security.SecureRandom());
                HttpsURLConnection
                                .setDefaultSSLSocketFactory(sc.getSocketFactory());
        } catch (Exception e) {
                e.printStackTrace();
        }
    }
   
    final static HostnameVerifier DO_NOT_VERIFY = new HostnameVerifier() {
        @Override
        public boolean verify(String hostname, SSLSession session) {
            return true;
        }
    };
}
[/code]
 
Posted by 머드초보
,
 
HttpClient 4.x버전으로 올라오면서 조쿰 바뀐 것 같습니다.
기록용으로 기록합니다-_-
아래 예제는.....티월드사이트의 무료사용량 조회 예제입니다-_-










[code]
import java.net.URI;
import java.util.ArrayList;
import java.util.List;

import org.apache.http.Header;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.BasicResponseHandler;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;

public class Main {

    /**
     * @param args
     */
    public static void main(String[] args) throws Exception{
        HttpClient httpclient = new DefaultHttpClient();
       
        String id = "t월드 아이디";
        String pw = "비밀번호";
       
        List<NameValuePair> qparams = new ArrayList<NameValuePair>();
        qparams.add(new BasicNameValuePair("URL", "http://www.tworld.co.kr/loginservlet.do?returnURL=http%3A%2F%2Fwww.tworld.co.kr&kind=&popup=&cmd=&reload=&ID=" + id));
        qparams.add(new BasicNameValuePair("ID", id));
        qparams.add(new BasicNameValuePair("PASSWORD", pw));
        qparams.add(new BasicNameValuePair("SERVERIP", "203.236.20.129"));
        qparams.add(new BasicNameValuePair("X", "0"));
        qparams.add(new BasicNameValuePair("Y", "0"));
        UrlEncodedFormEntity entity = new UrlEncodedFormEntity(qparams, "UTF-8");
        HttpPost httpPost = new HttpPost("http://nicasams.sktelecom.com:2040/icas/fc/LogOnSV");
        httpPost.setEntity(entity);
       
        ResponseHandler<String> responseHandler = new BasicResponseHandler();
        String responseBody = "";
        HttpResponse response = httpclient.execute(httpPost);
        Header[] headers  = response.getAllHeaders();
        httpclient = new DefaultHttpClient();
        HttpGet httpGet = new HttpGet();
        if (headers.length > 1){
            String url = headers[1].getValue();
            System.out.println("url = " + url);
            httpGet.setURI(new URI(url));
            responseBody = httpclient.execute(httpGet, responseHandler);
            System.out.println(responseBody);
        }
        httpGet.setURI(new URI("http://www.tworld.co.kr/normal.do?serviceId=S_BILL0070&viewId=V_CENT0261"));
        responseBody = httpclient.execute(httpGet, responseHandler);
       
        System.out.println("result = " + responseBody);
    }
}
[/code]

 
Posted by 머드초보
,
 
안드로이드는 개발환경 구축이 좀 빡세네요.
Java는 원래 다 그런 것인가....-_- 자바는 셋팅이 반이라는 말이 있는데, 이놈은 셋팅도 다시 해야하고, 사실 언어만 java지 안드로이드에 맞는 class와 구조를 다시 배워야하는 거라 자바를 좀 안다는 사람이나 자바를 전혀 모르는 사람이나 뭐 차이가 없습니다.

그리고, AVD(Android Vritual Device)라고 해서 가상 에뮬레이터에서 실행할 수 있고, 모토로이에서도 실행할 수 있는데, 일단 가상에뮬레이터는 좀 느립니다. EditText부분에 글을 쓸 때 반응속도가 너무 느려서 짜증이 밀려내려옵니다.
그래서 개발할 때에는 모토로이에서 하고, 테스트할 때에는 에뮬레이터에서 하는 게 정신 건강에 좀 좋을 듯 합니다. 모토로이에서 개발하고 다른 해상도가 틀린 디바이스 때문에 에뮬레이터에서 테스트해줘야겠죠^^
사실 모토로이에서 디버깅하고 개발하는 게 의외로 편하고 잘 되어있습니다. 정말 신기했습니다^^

일단 셋팅에 대한 많은 글들이 있는데요.
http://john.tobe30.com/tc/292
http://blog.naver.com/ksewookk/100099954283
http://ihoney.pe.kr/entry/01-Android-%EC%84%A4%EC%B9%98%EB%B0%A9%EB%B2%95-%EB%B0%8F-%EC%98%88%EC%A0%9C-%EC%8B%A4%ED%96%89

여기 글들을 참조해서 셋팅을 하세요~
아....모토로이는 버전이 2.0.1이 탑재되어있습니다. 참고하세요~

그럼 프로젝트를 만들고 디버깅을 해봅시다.

1. 프로젝트 생성
Android Project -> Project name에는 TestDebug, Build Target은 2.0.1, Application name은 디버깅테스트, package name은 com.mudchobo.testdebug, Create Activity는 TestDebug 후 Finish.

EditText에 이름을 쓰고, Button을 누르면 Hello, 이름 이라는 어플을 만들겁니다.
main.xml파일 수정
[code]
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
>
<EditText
    android:hint="이름입력하세요"
    android:id="@+id/etHello"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:inputType="textShortMessage"
/>
   
<Button
    android:text="sayHello"
    android:id="@+id/btnHello"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
/>
<TextView 
    android:id="@+id/tvHello"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:text="@string/hello"
/>
</LinearLayout>
[/code]
AndroidManifest.xml파일을 선택하고, Application탭을 선택하게 되면 Application Attributes에 Debuggable옵션이 있는데 이걸 true로 줘야합니다.

그럼 src -> com.mudchobo.testdebug패키지에 있는 TestDebug.java파일을 수정해봅시다.
[code]package com.mudchobo.testdebug;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

public class TestDebug extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
       
        // 버튼에 이벤트 추가
        Button btnHello = (Button) findViewById(R.id.btnHello);
       
        // 버튼클릭 시 리스너추가
        btnHello.setOnClickListener(new View.OnClickListener() {
           
            @Override
            public void onClick(View v) {
                // edittext값 가져오기
                EditText etHello = (EditText) findViewById(R.id.etHello);
                String sayHello = etHello.getText().toString();
               
                // 값을 textview에 셋팅
                TextView tvHello = (TextView) findViewById(R.id.tvHello);
                tvHello.setText(sayHello + ", Hello!");
            }
        });
       
    }
}[/code]
그냥 버튼에 이벤트 추가하고, 버튼클릭 시 값가져와서 값을 셋팅하는 초간단 예제입니다.

2. 디버깅 포인트 잡기
EditText etHello~~ 부분에 Ctrl + Shift + B를 누르거나 맨 앞에 더블클릭해서 Break Point를 잡습니다.
그리고 TestDebug에 오른쪽버튼 누르고, Debug As -> Android Application을 선택하면 실행합니다.
AVD가 떠 있다면 떠 있는 곳으로 어플을 설치하며 실행하고, 없으면 직접 AVD를 실행해서 설치하여 실행합니다.
AVD를 미리 띄워놓고 하는 게 정신건강에 좋습니다. 안그러면 프로그램에 끝나는 순간 AVD도 같이 죽어버립니다-_- 나중에 다시 시작하려고 하면 또 AVD를 부팅하는 꼴이 되어버립니다-_-

암튼, 실행하고 EditText에 말을 입력하고 버튼을 누르면 breakpoint에서 멈출겁니다. 이제 디버깅 하면 됩니다.

3. 모토로이에서 디버깅
이제 모토로이에서 실행해봅시다.

일단 모토로이를 디버깅 가능하게 셋팅해야 합니다.
설정 -> 응용프로그램 -> 개발 -> USB 디버깅 체크하셔서 활성화 시켜주세요.

모토로이를 usb에 연결합니다.
그리고 위와 같이 디버깅을 시작합니다. 그러면 이창이 뜰꺼에요.
사용자 삽입 이미지
이미 띄워놓은 AVD로 실행할래? 모토로이로 실행할래 물어보는 것인 듯. AVD를 띄워놓지 않으면 뜨지 않습니다. 바로 모토로이로 디버깅을 하더군요.
사용자 삽입 이미지
와....디버깅이 잘되네요. 에뮬레이터에서 타이핑 테스트하다 야마돌지 마시고, 모토로이에서 디버깅을 하시길-_-

4. 테스트하고 남은 어플 지우기
그리고 테스트하고 남은 어플은 여기서 지우시면 됩니다.
설정 -> 응용프로그램 -> 응용프로그램 관리 -> 디버그테스트(아까 프로젝트 만들 때 Application Name을 찾으면 됩니다. abcd가나다 순이니 참고하시길^^)선택 후 제거하면 됩니다.

PS. 뭐 별것도 없는 글을 장문으로 써버렸네-_-
 
Posted by 머드초보
,
 
앱엔진에 뭔가 제 사이트를 만들고 싶어서 이렇게 삽질을 하고 있는데, 망할 제한이 왜이렇게 많지-_-

암튼, "구글 앱 엔진"에서는 JPA를 지원합니다. 하지만, 이상하게도 잘 안됩니다-_- 굉장히 제한적으로 이것저것 막아둔 것 같습니다. 사실 구글 앱 엔진에서는 DataBase를 BigTable인지 뭐시기인지 그걸 사용하고, 직접적으로 접근을 못하기 때문에(전부 프로그래밍 또는 관리페이지(관리페이지도 매우 제한적인-_-)에서만 관리 가능), 이걸 이용하는 API에서도 엄청나게 뭔가 막아둔 것 같습니다.
뭐 좀 해보려고 하면 에러를 내뱉습니다. 검색해보면 구글앱엔진에서만 나는 에러입니다-_- 사실 아직 구글앱엔진이 프리뷰버전이기에 뭐라 따지지도 못하는 게 사실입니다^^ 정식버전(언제나오려나....Beta딱지 떼는데 10년넘게 걸리겠지-_-)나오면 매우 안정화가 되지 않을까 싶습니다^^

암튼, Spring3 + JPA의 조합으로 앱엔진에 올리는 건 성공했는데, 사실 스프링에서 제공하는 TransactionManager를 사용했어야 했는데, JPATemplate으로 뭔가 처리를 하면 잘 안되더군요-_- 일단 가져오고, persist하고, 이런건 잘 되는데, 왜 삭제가 안될까요-_- 삭제가 안되서 그냥JPATemplate빼고 했습니다-_-
JPATemplate사용해서 성공하신 분 트랙백좀 ㅠㅠ

0. 환경
Eclipse 3.5 + Google AppEngine Plugin + Spring 3.0.0
일단 스프링3다운로드 - http://www.springsource.org/download

1. 프로젝트 생성
New Project -> Google에 있는 Web Application Project 선택.
Project Name은 SosiSchedule. package는 com.mudchobo.
Use Google Web Toolkit은 체크해제. 사용안할꺼라....(이것도 언제한번 공부해야하는데-_-)
Finish.

2. 라이브러리 복사 및 build path추가
spring3에서는 spring.jar가 산산조각 났어요. 필요한 것만 넣으면 되는 듯.
일단 제가 사용한 것은....
org.springframework.asm-3.0.0.RELEASE.jar
org.springframework.beans-3.0.0.RELEASE.jar
org.springframework.context-3.0.0.RELEASE.jar
org.springframework.core-3.0.0.RELEASE.jar
org.springframework.expression-3.0.0.RELEASE.jar
org.springframework.orm-3.0.0.RELEASE.jar
org.springframework.web.servlet-3.0.0.RELEASE.jar
org.springframework.web-3.0.0.RELEASE.jar
그리고, jstl을 사용할 것이기에....
jstl.jar와 standard.jar
※이번버전에서는 lib폴더가 없습니다-_- 어디서 찾아야하는 거지-_- 암튼 그래서 2.5.6버전에서 가져왔습니다^^

앱엔진에서는 lib폴더 복사로 libpath가 잡히지 않네요. 그래서 각각 다 추가해줘야한다는...-_-
일단 war/WEB-INF/lib폴더에 복사 후에 복사한 파일 선택 후 오른쪽버튼 후, Build Path -> Add to Build Path 선택하면 됩니다^^

3. web.xml파일 수정
web.xml
[code]<servlet>
    <servlet-name>dispatcher</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <load-on-startup>2</load-on-startup>
</servlet>

<servlet-mapping>
    <servlet-name>dispatcher</servlet-name>
    <url-pattern>/sosischedule/*</url-pattern>
</servlet-mapping>

<welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
</welcome-file-list>[/code]
일단 sosischedule/*요청은 spring이 받습니다.

4. dispacher-servlet.xml파일과 persistence.xml파일 생성
war/WEB-INF/폴더에 생성
dispatcher-servlet.xml
[code]<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:p="http://www.springframework.org/schema/p"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

    <context:component-scan base-package="com.mudchobo" />
   
    <bean id="entityManager"
        factory-bean="EMF"
        factory-method="get" />
   
    <bean id="viewResolver"
        class="org.springframework.web.servlet.view.InternalResourceViewResolver"
        p:prefix="/WEB-INF/jsp/" p:suffix=".jsp" />
</beans>[/code]

src/META-INF/ 폴더에 생성
persistence.xml
[code]<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
        http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd" version="1.0">
   
    <persistence-unit name="transactions-optional">
        <provider>org.datanucleus.store.appengine.jpa.DatastorePersistenceProvider</provider>
        <properties>
            <property name="datanucleus.NontransactionalRead" value="true"/>
            <property name="datanucleus.NontransactionalWrite" value="true"/>
            <property name="datanucleus.ConnectionURL" value="appengine"/>
        </properties>
    </persistence-unit>
</persistence>[/code]

5. EMF클래스 생성.
이제 jpa접근할 수 있는 EntityManagerFactory클래스(EMF)를 생성해봅시다.
com.mudchobo.sosi.sosischedule.dao.EMF.java
[code]package com.mudchobo.sosischedule.dao;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;

import org.springframework.stereotype.Component;

@Component
public final class EMF {
     private static final EntityManagerFactory emfInstance =
        Persistence.createEntityManagerFactory("transactions-optional");

    private EMF() {}

    public EntityManager get() {
        return emfInstance.createEntityManager();
    }
}[/code]

6. Entity클래스 생성
일단 Sosi와 Schedule이라는 Entity를 생성할 건데요. 둘의 관계는 1:N관계입니다.
com.mudchobo.sosischedule.entity.Sosi.java
[code]package com.mudchobo.sosischedule.entity;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;

import com.google.appengine.api.datastore.Key;

@Entity
public class Sosi implements Serializable {
    private static final long serialVersionUID = 5448408922872112420L;

    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    private Key key;
   
    private String sosiName;
   
    @OneToMany(mappedBy="sosi", cascade=CascadeType.ALL)
    private List<Schedule> scheduleList = new ArrayList<Schedule>();

    public Key getKey() {
        return key;
    }

    public void setKey(Key key) {
        this.key = key;
    }

    public List<Schedule> getScheduleList() {
        return scheduleList;
    }

    public void setScheduleList(List<Schedule> scheduleList) {
        this.scheduleList = scheduleList;
    }

    public String getSosiName() {
        return sosiName;
    }

    public void setSosiName(String sosiName) {
        this.sosiName = sosiName;
    }

    public Sosi() {
       
    }
   
    public Sosi(Key key, String sosiName) {
        super();
        this.key = key;
        this.sosiName = sosiName;
    }
}[/code]
com.mudchobo.sosischedule.entity.Schedule.java
[code]package com.mudchobo.sosischedule.entity;

import java.io.Serializable;

import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToOne;

import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.KeyFactory;

@Entity
public class Schedule implements Serializable{
    private static final long serialVersionUID = -8676837674549793653L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Key key;
   
    private String program;
   
    @ManyToOne(fetch=FetchType.LAZY)
    private Sosi sosi;
   
    public Sosi getSosi() {
        return sosi;
    }

    public void setSosi(Sosi sosi) {
        this.sosi = sosi;
    }

    public Key getKey() {
        return key;
    }

    public void setKey(Key key) {
        this.key = key;
    }
   
   
    public String getKeyString() {
        return KeyFactory.keyToString(key);
    }
   
    public String getProgram() {
        return program;
    }

    public void setProgram(String program) {
        this.program = program;
    }
   
    public Schedule() {
    }

    public Schedule(String program, Sosi sosi) {
        this.program = program;
        this.sosi = sosi;
    }
}[/code]
일단 App Engine용 JPA에서는 ID 타입이 Long이면 관계형태를 사용할 수 없더라구요. 그래서 앱엔진에서 제공하는 Key타입이 있는데, 이걸 이용해야합니다.

7. Dao만들기
com.mudchobo.sosisochedule.SosiDao.java
[code]package com.mudchobo.sosischedule.dao;

import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.Query;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import com.google.appengine.api.datastore.KeyFactory;
import com.mudchobo.sosischedule.entity.Schedule;
import com.mudchobo.sosischedule.entity.Sosi;

@Repository
public class SosiDao {
    private EntityManager em;
   
    @Autowired
    public void setEntityManager(EntityManager em) {
        this.em = em;
       
        // 소시데이터 추가
        addSosi(new Long(1), "효연");
        addSosi(new Long(2), "윤아");
        addSosi(new Long(3), "수영");
        addSosi(new Long(4), "유리");
        addSosi(new Long(5), "태연");
        addSosi(new Long(6), "제시카");
        addSosi(new Long(7), "티파니");
        addSosi(new Long(8), "써니");
        addSosi(new Long(9), "서현");
    }
   
    public void addSosi(Long id, String sosiName) {
        em.getTransaction().begin();
        em.persist(new Sosi(KeyFactory.createKey(Sosi.class.getSimpleName(), id), sosiName));
        em.getTransaction().commit();
    }
   
    @SuppressWarnings("unchecked")
    public List<Sosi> getSosiList() {
        return em.createQuery("select s from Sosi s").getResultList();
    }

    public Sosi getSosi(Long sosiId) {
        return em.find(Sosi.class, sosiId);
    }
   
    @SuppressWarnings("unchecked")
    public List<Schedule> getScheduleList(final Long sosiId) {
        Query q = em.createQuery("select s.scheduleList from Sosi s where s.key = :key");
        q.setParameter("key", KeyFactory.createKey(Sosi.class.getSimpleName(), sosiId));
        return (List<Schedule>) q.getSingleResult();
    }
   
    public void addSchedule(Long sosiId, String program) {
        em.getTransaction().begin();
        Sosi sosi = em.find(Sosi.class, sosiId);
        sosi.getScheduleList().add(new Schedule(program, sosi));
        em.getTransaction().commit();
    }
   
    public void deleteSchedule(String scheduleKey) {
        em.getTransaction().begin();
        Schedule schedule = em.find(Schedule.class, scheduleKey);
        em.remove(schedule);
        em.getTransaction().commit();
    }
}[/code]
EntityManager받을 때 디폴트로 데이터를 넣어줘야 합니다(아까 위에서 말했듯이 프로그래밍적으로만 테이블을 생성할 수 있어서 이런 형태로 데이터를 넣어줘야합니다ㅠㅠ)

일단 실행해보고 데이터가 잘 생성되었는지 보려면 아래와 같은 주소로 접속해보면 됩니다.
http://localhost:8888/_ah/admin
일단 보고 삭제까지는 되는데, 테이블 생성같은 건 안되더라구요. 그리고 여기서 보여지는데에는 한글이 깨지는데 나중에 출력해보면 잘 나오니 걱정마시길-_-
사용자 삽입 이미지
8. Service 클래스 생성
com.mudchobo.sosischedule.service.SosiService.java
[code]package com.mudchobo.sosischedule.service;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.mudchobo.sosischedule.dao.SosiDao;
import com.mudchobo.sosischedule.entity.Schedule;
import com.mudchobo.sosischedule.entity.Sosi;

@Service
public class SosiService {
   
    @Autowired
    private SosiDao sosiDao;
   
    public List<Sosi> getSosiList()
    {
        return sosiDao.getSosiList();
    }
   
    public Sosi getSosi(Long sosiId) {
        return sosiDao.getSosi(sosiId);
    }
   
    public List<Schedule> getScheduleList(Long sosiId) {
        return sosiDao.getScheduleList(sosiId);
    }
   
    public void deleteSchedule(String scheduleKey) {
        sosiDao.deleteSchedule(scheduleKey);
    }

    public void addSchedule(Long sosiId, String program) {
        sosiDao.addSchedule(sosiId, program);
    }
}[/code]
Service에서 하는 역할은 뭐 없네요-_-

9. Controller생성
스프링3.0에서 새로 추가된 기능인 REST기능입니다.
com.mudchobo.sosischedule.controller.SosiController.java
[code]package com.mudchobo.sosischedule.controller;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;

import com.mudchobo.sosischedule.entity.Schedule;
import com.mudchobo.sosischedule.entity.Sosi;
import com.mudchobo.sosischedule.service.SosiService;

@Controller
public class SosiController {
    private static String PREFIX = "/sosischedule";
   
    @Autowired
    private SosiService sosiService;
   
    @RequestMapping(value="/", method=RequestMethod.GET)
    public String index(Model model) {
        List<Sosi> sosiList = sosiService.getSosiList();
        model.addAttribute("sosiList", sosiList);
       
        return "index";
    }
   
    @RequestMapping(value="/schedule/{sosiId}", method=RequestMethod.GET)
    public String getSchedule(
            @PathVariable("sosiId") Long sosiId,
            Model model) {
        Sosi sosi = sosiService.getSosi(sosiId);
        List<Schedule> scheduleList = sosiService.getScheduleList(sosiId);
        model.addAttribute("scheduleList", scheduleList)
            .addAttribute("sosi", sosi);
       
        return "sosi";
    }
   
    @RequestMapping(value="/schedule/{sosiId}/add", method=RequestMethod.POST)
    public String addSchedule(
            @PathVariable("sosiId") Long sosiId,
            @RequestParam("program") String program,
            Model model
            ) {
        sosiService.addSchedule(sosiId, program);
       
        return "redirect:" + PREFIX + "/schedule/" + sosiId;
    }
   
    @RequestMapping(value="/schedule/{sosiId}/{scheduleKey}", method=RequestMethod.GET)
    public String removeSchedule(
            @PathVariable("sosiId") Long sosiId,
            @PathVariable("scheduleKey") String scheduleKey,
            Model model) {
        sosiService.deleteSchedule(scheduleKey);
       
        return "redirect:" + PREFIX + "/schedule/" + sosiId;
    }
}[/code]

10. View jsp파일 생성
소시 리스트를 보여주는 index파일 입니다.
war/WEB-INF/jsp/index.jsp
[code]<%@ page language="java" contentType="text/html; charset=utf-8"
    pageEncoding="UTF-8"%>
<%@ page isELIgnored="false" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!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>소녀시대 스케줄</title>
</head>
<body>
    <div>
        스케줄 확인하기
        <ul>
        <c:forEach var="sosi" items="${sosiList}">
            <li><a href="/sosischedule/schedule/${sosi.key.id}">${sosi.key.id}. ${sosi.sosiName}</a></li>
        </c:forEach>
        </ul>
    </div>
</body>
</html>[/code]

해당 소시의 스케줄을 보여주는 스케줄 파일입니다.
war/WEB-INF/jsp/sosi.jsp
[code]<%@ page language="java" contentType="text/html; charset=utf-8"
    pageEncoding="UTF-8"%>
<%@ page isELIgnored="false" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!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>소녀시대 스케줄</title>
</head>
<body>
    <div>
        스케줄 확인하기
        <ul>
        <c:forEach var="sosi" items="${sosiList}">
            <li><a href="/sosischedule/schedule/${sosi.key.id}">${sosi.key.id}. ${sosi.sosiName}</a></li>
        </c:forEach>
        </ul>
    </div>
</body>
</html>[/code]
리다이렉트를 위한 파일입니다. 기존 index.html파일 지우시고, index.jsp파일 생성
index.jsp
[code]<% response.sendRedirect("/sosischedule/"); %>[/code]

앱엔진에 올려보았습니다.
http://2.latest.mudchobosample.appspot.com/sosischedule/

잘 되는 것 같네요.
 
Posted by 머드초보
,
 
Netbeans에서도 Google App Engine플러그인을 설치해서 개발할 수 있습니다.
하지만, 구글에서 공식적으로 제공하는 플러그인이 아니라 누가 만든 것 같네요.

이곳에서 보고 설치 및 샘플을 실행할 수 있습니다.

아.....이건 상관없는 그림이지만, 그림을 보면 볼수록 왠지 슬퍼지는데요.
오늘 권순선님 미투데이에서 발견했습니다-_-
사용자 삽입 이미지

Java를 낳고 돌아가신 Sun이군요-_- 오라클이 인수하는 걸 EC에서 승인했다더군요.



암튼 대충 따라해보면...

1. 플러그인 설치
Tools -> Plugins -> Settings -> Add -> Name에 App Engine이라고 하고, URL에 아래 주소를 입력
그러면 Available Plugins에 5개의 Google App Engine플러그인이 생김. 체크해서 설치 고고싱

2. SDK다운로드
여기서 자바용으로 받아서 적당한 폴더에 풀어주면 됨 ㄷㄷ

3. Google App Engine 서버 설정
넷빈즈에서 Services탭에서 Servers에서 마우스 오른쪽버튼 클릭 후 Add Server선택
Google App Engine을 선택한 뒤, 위에서 받은 sdk폴더 경로 지정. 포트는 맘에 드는걸로 하면 끝남

4. 새로운 프로젝트 생성
New 프로젝트 -> Java Web -> Web Application -> Project Name은 HelloGoogleAppEngine -> Server는 Google App Engine -> Finish하면 끝남.
F6을 눌러서 실행하면 Hello World 볼 수 있음 ㄷㄷ

5. 배포
배포 시 Web Pages -> WEB-INF -> appengine-web.xml파일에서 Application Name을 자신이 얻은 Name으로 수정하고 해야함.

그런데 배포 시 약간 문제가 있음.
아무것도 안건드렸다고해도 이런 에러를 보게 될 꺼임.
[code]java.lang.IllegalStateException: cannot find javac executable based on java.home, tried "C:\Program Files\Java\jre6\bin\javac.exe" and "C:\Program Files\Java\bin\javac.exe"
Unable to update app: cannot find javac executable based on java.home, tried "C:\Program Files\Java\jre6\bin\javac.exe" and "C:\Program Files\Java\bin\javac.exe"
Please see the logs [C:\Users\mudchobo\AppData\Local\Temp\appcfg7950519452562723725.log] for further information.[/code]
javac파일을 java\bin에서 찾는 것 같음. 거기엔 javac.exe파일이 없음. java.home위치를 수정하는 법을 몰라서, 검색해보니 그냥 그 폴더에 javac.exe를 복사하는 거임. tools.jar파일도 lib폴더에 같이 복사해야함 ㄷㄷ

제꺼기준으로
C:\Program Files\Java\jdk1.6.0_17\bin\javac.exe파일을 -> C:\Program Files\Java\jre6\bin에 복사.
C:\Program Files\Java\jdk1.6.0_17\lib\tools.jar파일을 -> C:\Program Files\Java\jre6\lib\폴더에 복사.

그러면 잘 될꺼임.

ps. 결론은.......그냥 이클립스 플러그인 쓰는 게 나아요. 그건 GWT연동도 되거든요-_- 이런 짓을 하면서 까지 넷빈즈에서 개발하고 싶진 않은 듯. 공식으로 지원하는 플러그인으로....-_- 이클립스가 짱인 듯.
 
Posted by 머드초보
,