728x90

자바의 InputStream과 OutputStream은 외부와의 I/O를 위한 인터페이스를 제공한다.

이번에 다룰 주제인 InputStream은 I/O 중 I에 대한 부분을 다룬다.

 

대표적인 3가지 사용처는 콘솔과의 표준 입출력, 파일 입출력, 소켓과의 입출력이다.

 

오늘 다룰 내용은 자바 ee 어플리케이션에서의 inputstream이다.

 

자바 ee 서버에서는 HttpServletRequest가 존재하고,

이 클래스를 통해 inputstream을 가져올 수 있게 되어 있다. 

그렇기 때문에, request.getInputStream(); 과 같은 형태로 서블릿 내에서 inputstream을 받아와 사용할 수 있는 것이다.

톰캣에서는 CoyoteInputStream이란 이름으로 단일한 형태의 inputstream을 제공하고,

제우스의 경우에는 요청의 종류에 따라 WjpInputStream, Ajp13InputStream, ServletInputStreamImpl을 제공한다.

 

오늘 다룰 내용은 inputstream 사용 시에 주의할 점에 대한 내용이다.

 

다시 한번 말하지만, inputstream은 외부와 통신하기 위한 인터페이스이다.

자바는 C언어와 다르다.

OS의 민감한 부분에 직접적으로 접근하는 부분은 jdk에서 제공한 수단으로만 접근할 수 있다는 점에 유의한다.

 

inputstream은 기본적으로 socket에서 가져온 inputstream을 사용한다.

그리고, read 메서드를 호출하면, 인자에 따라 1byte를 읽거나, 정해진 양만큼 읽어오려고 시도한다.

어플리케이션에서 요구한 양보다 버퍼에 있는 양이 더 적으면, 그냥 적은걸 던져준다.

-1을 리턴하는 경우는 연결이 끊겼을 때이고, 단순히 읽을 것이 없는 경우엔 0을 던저주는 것이 아니라, blocking 된다.

 

따라서 만약에 어플리케이션이 구현이 잘못되었다면, 

 

1. read 메서드에 의해 blocking이 될 수 있다.

2. 읽어오고자 하는 데이터를 전부다 읽어오지 못할 수도 있다. 

 

위와 같은 위험성을 제거하기 위해, inputstream은 available 메서드를 제공한다. 

available 메서드는 지금 읽어올 수 있는 데이터의 양을 제공해주는 메서드이다.

이 메서드의 이름만 봐서는 현재 읽을 수 있는 값을 정확하게 돌려줄 수 있을 것 같다.

그러나 결코 그렇지 않기 때문에 사용에 많은 주의가 필요하다.

 

엄밀히 말하면, 이 메서드는 "현재 확실히 읽을 수 있는 버퍼의 크기"를 제공한다.

java doc에 가보면, "estimated value"를 제공한다고 되어 있다.

이는 이 메서드가 call 되는 시점과, 버퍼가 차오르는 시점이 다를수 있기 때문이다.

available 메서드로 얼마나 읽을 수 있을지 확인하고 있는 그 시점에도, 

새로운 데이터는 버퍼에 계속 쌓이고 있기 때문이다. 

 

이 때문에, available 메서드가 의도한대로 동작하지 않는 경우도 존재한다.

예를 들어, available이 0일 때, 루프를 탈출하도록 작성했다고 가정한다.

 

InputStream is = socket.inputStream();

while(is.available()>0) {}

클라이언트에서 데이터를 보내도, 해당 루프를 아예 돌지 않을 수 있다는 것이다.

왜냐하면, is.available을 호출하는 시점에는 클라이언트에서 보낸 데이터가 도착하지 않았지만,

그 이후엔 계속 클라이언트에서 보낸 데이터가 버퍼에 쌓일 수 있다. 

 

자바 ee 서버에서는 inputstream 구현체를 만들면서(tomcat의 경우 CoyoteInputStream),

해당 메서드도 오버라이드 해버리는 경우도 있어 위 설명과 동작이 다를 수도 있다.

어찌되었든 그로 인해 다른 문제가 생길수도 있기 때문에 문서를 보거나 구현을 확인한 후에 사용하도록 하자.

 

결론은 아래와 같다.

 

자바 어플리케이션 내에서 inputstream으로 값을 읽어올 때에는, 위의 상황을 고려하지 않으면,

데이터를 끝까지 읽지 못하거나, blocking이 될 위험성이 있다. 

그렇기 때문에 자바 어플리케이션 내에서 inputstream으로 값을 읽어올 때에는 주의가 필요하다.

 

특히 tomcat의 AJP 프로토콜은 read 메서드로 한번에 8186바이트만 읽을 수 있기 때문에,

그거보다 큰 데이터를 읽어오는 경우엔 별도의 처리를 해주는게 맞아보인다.

 

참고로 request#getParameter() 메서드로 호출할 때에는, http header에 포함된 content-length 만큼 데이터를 읽어

맵을 만들도록 구현하기 때문에, 이 문제에 대해 고려할 필요가 없다.

 

https://jongqui.tistory.com/6

 

 

 

 

728x90

Luna HSMs have many capabilities that are not certified by NIST. To be FIPS-compliant, the HSM must be set to FIPS mode, where any mechanisms or cryptographic operations that are not FIPS-certified are blocked from use. FIPS mode is set using HSM or partition policies as described below.

 

Setting FIPS Mode on the HSM

You can set the HSM to FIPS mode using HSM policy 12: Allow non-FIPS algorithms. When this policy is set to 0, algorithms that are not FIPS-validated are blocked from use on every partition on the HSM, and the HSM is operating in FIPS mode. There are two methods of setting this policy:

>The HSM SO can use a policy template to set the policy at initialization (see Setting HSM Policies Using a Template). This method is recommended for auditing purposes -- it ensures that the HSM is in FIPS mode for its entire use cycle.

>The HSM SO can set the policy manually after initializing the HSM (see Setting HSM Policies Manually).

'Cryptography' 카테고리의 다른 글

HOTP and TOTP  (31) 2024.03.21
The group Zp*  (31) 2024.03.11
Padding oracles and the decline of CBC-mode cipher suites  (80) 2024.03.08
CBC-bit Flipping  (18) 2024.03.08
AES Cipher  (0) 2024.03.07
728x90

JSONException and JSONObject components called from JSON Library were not imported in Jenkins compiling stage.

Components are not included in or are not recognized at the JVM level, which is expected.

 

Despite these issues causing some users, I have no idea why they happen.

 

Change Below 

import org.springframework.boot.configurationprocessor.json.JSONObject;
import org.springframework.boot.configurationprocessor.json.JSONException;

 

to

import org.json.JSONException;
import org.json.JSONObject;

 

Also, import JSON directly

implementation 'org.json:json:20240303'

 

'Java > Spring Boot JPA' 카테고리의 다른 글

JobParametersIncrementer  (0) 2024.04.03
Running Jobs from within a Web Container  (31) 2024.04.03
Builder and AllArgsConstructor Annotation  (31) 2024.04.02
Item Processing in Spring Batch  (0) 2024.04.01
ItemReaders and ItemWriters  (31) 2024.03.27
728x90

JobParametersIncrementer

Most of the methods on JobOperator are self-explanatory, and you can find more detailed explanations in the Javadoc of the interface. However, the startNextInstance method is worth noting. This method always starts a new instance of a Job. This can be extremely useful if there are serious issues in a JobExecution and the Job needs to be started over again from the beginning. Unlike JobLauncher (which requires a new JobParameters object that triggers a new JobInstance), if the parameters are different from any previous set of parameters, the startNextInstance method uses the JobParametersIncrementer tied to the Job to force the Job to a new instance:

 

public interface JobParametersIncrementer {

    JobParameters getNext(JobParameters parameters);

}

 

 

The contract of JobParametersIncrementer is that, given a JobParameters object, it returns the “next” JobParameters object by incrementing any necessary values it may contain. This strategy is useful because the framework has no way of knowing what changes to the JobParameters make it the “next” instance. For example, if the only value in JobParameters is a date and the next instance should be created, should that value be incremented by one day or one week (if the job is weekly, for instance)? The same can be said for any numerical values that help to identify the Job, as the following example shows:

 

public class SampleIncrementer implements JobParametersIncrementer {

    public JobParameters getNext(JobParameters parameters) {
        if (parameters==null || parameters.isEmpty()) {
            return new JobParametersBuilder().addLong("run.id", 1L).toJobParameters();
        }
        long id = parameters.getLong("run.id",1L) + 1;
        return new JobParametersBuilder().addLong("run.id", id).toJobParameters();
    }
}

 

In this example, the value with a key of run.id is used to discriminate between JobInstances. If the JobParameters passed in is null, it can be assumed that the Job has never been run before and, thus, its initial state can be returned. However, if not, the old value is obtained, incremented by one, and returned.

 

For jobs defined in Java, you can associate an incrementer with a Job through the incrementer method provided in the builders, as follows:

 

@Bean
public Job footballJob(JobRepository jobRepository) {
    return new JobBuilder("footballJob", jobRepository)
    				 .incrementer(sampleIncrementer())
    				 ...
                     .build();
}
Copied

+ Recent posts