method findOne() of JpaReposiroy Spring Data ? findOne is not applicable for the arguments (String) - eclipse

// Class CompteRepository
import org.springframework.data.jpa.repository.JpaRepository;
import org.entities.Compte;
public interface CompteRepository extends JpaRepository<Compte, String>{}
// CLASS BanqueMetierImpl``
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.data.domain.Page;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
#Service // SPring couche Metier
#Transactional
public class BanqueMetierImpl implements IBanqueMetier{
#Autowired
private CompteRepository compteRepository;
#Override
public Compte consulterCompte(String code) {
Compte cp = compteRepository.findOne(code);
return cp;
}
// The method findOne show up this error The method findOne(Example) in //the type QueryByExampleExecutor is not applicable for the arguments //(String)

I think the method findOne() is unsupported by version 1.5.1.SNAPSHOT of SPRING BOOT , so in 2.0.1.SNAPSHOT it's replaced by FindById() which is a QueryByExampleExecutor it's an Optional method (see Optional in JAVA 8) so I resolved the problem like this:
#Override public Compte consulterCompte(String code) throws NotFoundException {
Optional<Compte> cp = compteRepository.findById(code);
return cp.orElseThrow(
() -> new NotFoundException("Unable to get Account with Code = " + code)
);
}

Related

Replacing WebAuthenticationDetails with Webflux code

I am working on Spring boot 3 and want to convert non-reactive code to reactive code.
In non-reactive code, I use a class which extends WebAuthenticationDetails.
It needs to call default constructor with HttpServletRequest as parameter.
Now, as I want to move to Webflux[Reactive code]. I am removing "extends WebAuthenticationDetails".
And replacing HttpServletRequest with ServerWebExcahnge.
Is this approach correct?
Sample code:
Non-reactive Code:
import org.springframework.security.Authentication.AuthenticationDetailsSource;
class AuthSource implements AuthenticationDetailsSource<HttpServletRequest, Auth>{
#Override
public Auth buildDetails(HttpServletRequest req){
return new Auth(req);
}
}
class Auth extends WebAuthenticationDetails{
Auth(HttpServletRequest req){
super(req);
}
}
Reactive code:
import org.springframework.security.Authentication.AuthenticationDetailsSource;
class AuthReactiveSource implements AuthenticationDetailsSource<ServerWebExchange, AuthReactive>{
#Override
public AuthReactive buildDetails(ServerWebExchange req){
return new AuthReactive(req);
}
}
class AuthReactive{ // Not extending any class
AuthReactive(ServerWebExchange req){
}
}
Just to understand , Is this correct?

#DynamicPropertySource not being invoked (Kotlin, Spring Boot and TestContainers)

I'm trying to define a #TestConfiguration class that is executed once before all integration tests to run a MongoDB TestContainer in Kotlin in a Spring Boot project.
Here is the code:
import org.springframework.boot.test.context.TestConfiguration
import org.springframework.test.context.DynamicPropertyRegistry
import org.springframework.test.context.DynamicPropertySource
import org.testcontainers.containers.MongoDBContainer
import org.testcontainers.utility.DockerImageName
#TestConfiguration
class TestContainerMongoConfig {
companion object {
#JvmStatic
private val MONGO_CONTAINER: MongoDBContainer = MongoDBContainer(DockerImageName.parse("mongo").withTag("latest")).withReuse(true)
#JvmStatic
#DynamicPropertySource
private fun emulatorProperties(registry: DynamicPropertyRegistry) {
registry.add("spring.data.mongodb.uri", MONGO_CONTAINER::getReplicaSetUrl)
}
init { MONGO_CONTAINER.start() }
}
}
The issue seems to be that emulatorProperties method is not being called.
The regular flow should be that the container is started and then the properties are set.
The first step happens, the second does not.
I know there is an alternative for which I can do this configuration in each functional test class but I don't like it as it adds not needed noise to the test class.
For example, with a Java project that uses Postgres I managed to make it work with the following code:
import javax.sql.DataSource;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.boot.test.context.TestConfiguration;
import org.springframework.context.annotation.Bean;
import org.testcontainers.containers.PostgreSQLContainer;
import org.testcontainers.utility.DockerImageName;
#TestConfiguration
public class PostgresqlTestContainersConfig {
static final PostgreSQLContainer POSTGRES_CONTAINER;
private final static DockerImageName IMAGE = DockerImageName.parse("postgres").withTag("latest");
static {
POSTGRES_CONTAINER = new PostgreSQLContainer(IMAGE);
POSTGRES_CONTAINER.start();
}
#Bean
DataSource dataSource() {
return DataSourceBuilder.create()
.username(POSTGRES_CONTAINER.getUsername())
.password(POSTGRES_CONTAINER.getPassword())
.driverClassName(POSTGRES_CONTAINER.getDriverClassName())
.url(POSTGRES_CONTAINER.getJdbcUrl())
.build();
}
}
I'm trying to achieve the same thing but in Kotlin and using MongoDB.
Any idea on what may be the issue causing the #DynamicPropertySource not being called?
#DynamicPropertySource is part of the Spring-Boot context lifecycle. Since you want to replicate the Java setup in a way, it is not required to use #DynamicPropertySource. Instead you can follow the Singleton Container Pattern, and replicate it in Kotlin as well.
Instead of setting the config on the registry, you can set them as a System property and Spring Autoconfig will pick it up:
init {
MONGO_CONTAINER.start()
System.setProperty("spring.data.mongodb.uri", MONGO_CONTAINER.getReplicaSetUrl());
}
I was able to resolve similar problem in Groovy by:
Having static method annotated with #DynamicPropetySource directly in the test class (probably it would also work in superclass.
But I didn't want to copy the code into every test class that needs MongoDB.
I resolved the issue by using ApplicationContexInitializer
The example is written in groovy
class MongoTestContainer implements ApplicationContextInitializer<ConfigurableApplicationContext>{
static final MongoDBContainer mongoDBContainer = new MongoDBContainer(DockerImageName.parse("mongo:6.0.2"))
#Override
void initialize(ConfigurableApplicationContext applicationContext) {
mongoDBContainer.start()
def testValues = TestPropertyValues.of("spring.data.mongodb.uri="+ mongoDBContainer.getReplicaSetUrl())
testValues.applyTo(applicationContext.getEnvironment())
}
}
To make it complete, in the test class, you just need to add #ContextConfiguration(initializers = MongoTestContainer) to activate context initializer for the test.
For this you could also create custom annotation which would combine #DataMongoTest with previous annotation.
This solution works for me.
Method with #DynamicPropertySource is inside companion object(also added #JvmStatic) and added org.testcontainers.junit.jupiter.Testcontainers on the test class
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.extension.ExtendWith
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.jdbc.DataSourceBuilder
import org.springframework.boot.test.context.TestConfiguration
import org.springframework.context.annotation.Bean
import org.springframework.test.context.ContextConfiguration
import org.springframework.test.context.DynamicPropertyRegistry
import org.springframework.test.context.DynamicPropertySource
import org.springframework.test.context.junit.jupiter.SpringExtension
import org.testcontainers.containers.PostgreSQLContainer
import org.testcontainers.junit.jupiter.Container
import org.testcontainers.junit.jupiter.Testcontainers
import javax.sql.DataSource
#ExtendWith(SpringExtension::class)
#Testcontainers
#TestConfiguration
#ContextConfiguration(classes = [PostgresqlTestContainersConfig::class])
class PostgresqlTestContainersConfig {
#Autowired
var dataSource: DataSource? = null
#Test
internal fun name() {
dataSource!!.connection.close()
}
#Bean
fun dataSource(): DataSource? {
return DataSourceBuilder.create()
.username(POSTGRES_CONTAINER.getUsername())
.password(POSTGRES_CONTAINER.getPassword())
.driverClassName(POSTGRES_CONTAINER.getDriverClassName())
.url(POSTGRES_CONTAINER.getJdbcUrl())
.build()
}
companion object {
#JvmStatic
#Container
private val POSTGRES_CONTAINER: PostgreSQLContainer<*> = PostgreSQLContainer("postgres:9.6.12")
.withDatabaseName("integration-tests-db")
.withUsername("sa")
.withPassword("sa")
#JvmStatic
#DynamicPropertySource
fun postgreSQLProperties(registry: DynamicPropertyRegistry) {
registry.add("db.url") { POSTGRES_CONTAINER.jdbcUrl }
registry.add("db.user") { POSTGRES_CONTAINER.username }
registry.add("db.password") { POSTGRES_CONTAINER.password }
}
}
}

MIMEMessage and MIMEMessage mock test case fails with assertion error on EmailUtil

What I'm trying to achieve - Simple unit test for my EmailUtil which i have written for a Spring MVC application.
Where I'm stuck - Though i have mocked the MIMEmessage and JavaMailSender, test case failing in MimeMessageHelper.set**** methods.
Appreciate any help on this as I have tried few different ways even using PowerMock and no luck for last couple of days.
EmailUtil.Java
import java.util.List;
import javax.activation.DataSource;
import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;
import javax.mail.util.ByteArrayDataSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import com.dashboard.domain.Attachment;
import com.dashboard.domain.Email;
public class EmailUtil {
private static final Logger LOGGER = LoggerFactory.getLogger(EmailUtil.class
.getName());
/**
* Private constructor to make sure that no one creating instance
*/
private EmailUtil() {
}
/**
* Functionality to send the mail. This method used the mail sender
* configuration from spring-context file.
*
* #param email
* #param mailSender
* #throws MessagingException
*/
public static void sendEmail(JavaMailSender mailSender, Email email)
throws MessagingException {
LOGGER.info("Start of the method: sendEmail");
MimeMessage mimeMessage = mailSender.createMimeMessage();
// use the true flag to indicate you need a multi part message
boolean hasAttachments = email.getAttachments() != null
&& !email.getAttachments().isEmpty();
LOGGER.info(" mimeMessage - {} ",mimeMessage);
MimeMessageHelper helper = new MimeMessageHelper(mimeMessage,
hasAttachments);
LOGGER.info(" MimeMessageHelper - {} ",helper);
helper.setTo(email.getTo());
helper.setFrom(email.getFrom());
helper.setCc(email.getCc());
helper.setSubject(email.getSubject());
helper.setText(email.getText(), true);
List<Attachment> attachments = email.getAttachments();
if (!attachments.isEmpty()) {
for (Attachment attachment : attachments) {
String filename = attachment.getFilename();
DataSource dataSource = new ByteArrayDataSource(
attachment.getData(), attachment.getMimeType());
if (attachment.isInline()) {
helper.addInline(filename, dataSource);
} else {
helper.addAttachment(filename, dataSource);
}
}
}
mailSender.send(mimeMessage);
LOGGER.info("End of the method: sendEmail");
}
}
EmailUtilTest.Java
import static org.easymock.EasyMock.expect;
import javax.mail.Address;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMessage.RecipientType;
import org.easymock.EasyMock;
import org.easymock.Mock;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import com.dashboard.domain.ApplicationConstant;
import com.dashboard.domain.Email;
/**
* PowerMockDemo
* #author s.arumugam
*
*/
#RunWith(PowerMockRunner.class)
#PrepareForTest(EmailUtil.class)
public class EmailUtilTest {
Email email = new Email();
#Mock
JavaMailSender javaMailSender;
#Mock
MimeMessage mimeMessage;
#Mock
MimeMessageHelper mimeMessageHelper;
#Before
public void initList() {
email.setFrom(ApplicationConstant.DEFAULT_MAIL_ID.getValue());
email.setSubject("Subject");
email.setTo("to.email#userdomain.com");
email.setCc("admin#dashboard.com");
email.setText("Body of the email");
}
#Test
public void sendEmailTest() throws Exception{
mimeMessageHelper.setSubject(email.getSubject());
mimeMessageHelper.setFrom(new InternetAddress(email.getFrom(), true));
mimeMessageHelper.setCc(new InternetAddress(email.getCc()[0], true));
mimeMessageHelper.setTo(new InternetAddress(email.getTo()[0], true));
mimeMessageHelper.setText(email.getText());
expect(javaMailSender.createMimeMessage()).andReturn(mimeMessage);
Address sendTo[]={new InternetAddress(email.getTo()[0])};
mimeMessage.setRecipients(RecipientType.TO,sendTo);
EasyMock.expectLastCall().times(1);
EasyMock.replay(mimeMessage);
EasyMock.replay(javaMailSender);
EmailUtil.sendEmail(javaMailSender, email);
EasyMock.verify(mimeMessage);
EasyMock.verify(javaMailSender);
}
}
Error Message:
java.lang.AssertionError: Unexpected method call MimeMessage.setRecipients(To, [to.email#userdomain.com]):
MimeMessage.setRecipients(To, [to.email#userdomain.com]): expected: 1, actual: 0 at org.easymock.internal.MockInvocationHandler.invoke(MockInvocationHandler.java:44) at org.easymock.internal.ObjectMethodsFilter.invoke(ObjectMethodsFilter.java:94) at org.easymock.internal.ClassProxyFactory$MockMethodInterceptor.intercept(ClassProxyFactory.java:97) at $javax.mail.internet.MimeMessage$$EnhancerByCGLIB$$a6025b60.setRecipients(<generated>) at org.springframework.mail.javamail.MimeMessageHelper.setTo(MimeMessageHelper.java:581) at org.springframework.mail.javamail.MimeMessageHelper.setTo(MimeMessageHelper.java:595) at com.dashboard.util.EmailUtil.sendEmail(EmailUtil.java:50)
Ohh.. I managed to fix the issue.. purely by random trial and error..! That says I need to get into deep understanding of how these mock utils works.. Working test case below with a hope someone can find a complete working example with test case;
#RunWith(EasyMockRunner.class)
public class EmailUtilTest extends EasyMockSupport{
#Mock
JavaMailSender mailSender;
#Mock
MimeMessage mimeMessage;
#Test
public void testSendEmail() throws MessagingException{
Email email = new Email();
email.setFrom("from.email#dashboard.com");
email.setSubject("Subject");
email.setTo("to.email#userdomain.com");
email.setCc("admin#dashboard.com");
email.setText("Body of the email");
EasyMock.expect(mailSender.createMimeMessage()).andReturn(mimeMessage);
mailSender.send(mimeMessage);
EasyMock.expectLastCall();
EasyMock.replay(mailSender);
EmailUtil.sendEmail(mailSender, email);
EasyMock.verify(mailSender);
}
}
The reason you are getting java.lang.AssertionError is because EasyMock uses the equals() method to compare parameters passed to methods, and you cannot use equals() to compare arrays.
Address toAddress = new InternetAddress("a#b.com");
Address[] a1 = { toAddress };
Address[] a2 = { toAddress };
if (a1.equals(a2)) { // this will be false
// so this won't happen
}
Thankfully, EasyMock provides us with several different argument matchers. In this case we should use EasyMock.aryEq(). So in order to mock out the call to setRecipients() method:
mimeMessage.setRecipients(EasyMock.eq(RecipientType.TO) , EasyMock.aryEq(sendTo));
I'm not sure how the accepted answer is working without changes to the EmailUtil class.

Create Scalding Source like TextLine that combines multiple files into single mappers

We have many small files that need combining. In Scalding you can use TextLine to read files as text lines. The problem is we get 1 mapper per file, but we want to combine multiple files so that they are processed by 1 mapper.
I understand we need to change the input format to an implementation of CombineFileInputFormat, and this may involve using cascadings CombinedHfs. We cannot work out how to do this, but it should be just a handful of lines of code to define our own Scalding source called, say, CombineTextLine.
Many thanks to anyone who can provide the code to do this.
As a side question, we have some data that is in s3, it would be great if the solution given works for s3 files - I guess it depends on whether CombineFileInputFormat or CombinedHfs works for s3.
You get the idea in your question, so here is what possibly is a solution for you.
Create your own input format that extends the CombineFileInputFormat and uses your own custom RecordReader. I am showing you Java code, but you could easily convert it to scala if you want.
import java.io.IOException;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapred.FileSplit;
import org.apache.hadoop.mapred.InputSplit;
import org.apache.hadoop.mapred.JobConf;
import org.apache.hadoop.mapred.LineRecordReader;
import org.apache.hadoop.mapred.RecordReader;
import org.apache.hadoop.mapred.Reporter;
import org.apache.hadoop.mapred.lib.CombineFileInputFormat;
import org.apache.hadoop.mapred.lib.CombineFileRecordReader;
import org.apache.hadoop.mapred.lib.CombineFileSplit;
public class CombinedInputFormat<K, V> extends CombineFileInputFormat<K, V> {
public static class MyKeyValueLineRecordReader implements RecordReader<LongWritable,Text> {
private final RecordReader<LongWritable,Text> delegate;
public MyKeyValueLineRecordReader(CombineFileSplit split, Configuration conf, Reporter reporter, Integer idx) throws IOException {
FileSplit fileSplit = new FileSplit(split.getPath(idx), split.getOffset(idx), split.getLength(idx), split.getLocations());
delegate = new LineRecordReader(conf, fileSplit);
}
#Override
public boolean next(LongWritable key, Text value) throws IOException {
return delegate.next(key, value);
}
#Override
public LongWritable createKey() {
return delegate.createKey();
}
#Override
public Text createValue() {
return delegate.createValue();
}
#Override
public long getPos() throws IOException {
return delegate.getPos();
}
#Override
public void close() throws IOException {
delegate.close();
}
#Override
public float getProgress() throws IOException {
return delegate.getProgress();
}
}
#Override
public RecordReader getRecordReader(InputSplit split, JobConf job, Reporter reporter) throws IOException {
return new CombineFileRecordReader(job, (CombineFileSplit) split, reporter, (Class) MyKeyValueLineRecordReader.class);
}
}
Then you need to extend the TextLine class and make it use your own input format you just defined (Scala code from now on).
import cascading.scheme.hadoop.TextLine
import cascading.flow.FlowProcess
import org.apache.hadoop.mapred.{OutputCollector, RecordReader, JobConf}
import cascading.tap.Tap
import com.twitter.scalding.{FixedPathSource, TextLineScheme}
import cascading.scheme.Scheme
class CombineFileTextLine extends TextLine{
override def sourceConfInit(flowProcess: FlowProcess[JobConf], tap: Tap[JobConf, RecordReader[_, _], OutputCollector[_, _]], conf: JobConf) {
super.sourceConfInit(flowProcess, tap, conf)
conf.setInputFormat(classOf[CombinedInputFormat[String, String]])
}
}
Create a scheme for the for your combined input.
trait CombineFileTextLineScheme extends TextLineScheme{
override def hdfsScheme = new CombineFileTextLine().asInstanceOf[Scheme[JobConf,RecordReader[_,_],OutputCollector[_,_],_,_]]
}
Finally, create your source class:
case class CombineFileMultipleTextLine(p : String*) extends FixedPathSource(p :_*) with CombineFileTextLineScheme
If you want to use a single path instead of multiple ones, the change to your source class is trivial.
I hope that helps.
this should do the trick, ya man? - https://wiki.apache.org/hadoop/HowManyMapsAndReduces

Reusable Liferay (6.0.6) service

I am trying to implement resuable Custom Services without using ext and servicebuilder.
I referred this article: http://www.devatwork.nl/2010/04/implementing-a-reusable-liferay-service-without-ext-or-service-builder/ , but I am confused in how should I implement this using eclipse? Following are the steps that I followed to do this:
- Created liferay-plugin project within eclipse.
- Created package containing CustomServices (interface) and CustomServicesUtil.
- Created jar file of package in step 2.
- Placed that jar file in tomcat\lib\ext\
- Then created package (with in same liferay-plugin project), that includes CutomServicesImpl and CustomServicesBaseImpl
- Defined portlet-spring.xml, service.properties, and modified web.xml (as per the article), and finally deployed the project.
On deployment, project is deployed successfully, but when I am trying to use customMethods defined in CustomServicesImpl through CustomServicesUtil.getCustomMethod(), I am getting the following error:
"java.lang.ClassNotFoundException: com.demo.custom.services.CustomServicesUtil"
I configure build path to include customservices.jar file but its not working out, still showing the same error. I don’t know whether this is the correct way to implement resuable services or not. I tried this so that i can make use of custom method in one of my project.
Here is the code for custom services:
CustomServices.java
package com.demo.custom.services;
import com.liferay.portal.model.User;
public interface CustomServices {
String getCustomName(User user);
}
CustomServicesUtil.java
package com.demo.custom.services;
import com.liferay.portal.model.User;
public class CustomServicesUtil {
private static CustomServices services;
public static CustomServices getServices() {
if (services == null) {
throw new RuntimeException("Custom Services not set");
}
return services;
}
public void setServices(CustomServices pServices) {
services = pServices;
}
public static String getCustomName(User user){
return getServices().getCustomName(user);
}
}
CustomServicesBaseImpl.java
package com.demo.custom.services.impl;
import com.demo.custom.services.CustomServices;
import com.liferay.portal.kernel.exception.SystemException;
import com.liferay.portal.service.base.PrincipalBean;
import com.liferay.portal.util.PortalUtil;
public abstract class CustomServicesBaseImpl extends PrincipalBean implements CustomServices {
protected CustomServices services;
public CustomServices getServices() {
return services;
}
public void setServices(CustomServices pServices) {
this.services = pServices;
}
protected void runSQL(String sql) throws SystemException {
try {
PortalUtil.runSQL(sql);
} catch (Exception e) {
throw new SystemException(e);
}
}
}
CustomServicesImpl.java
package com.demo.custom.services.impl;
import com.liferay.portal.model.User;
public class CustomServicesImpl extends CustomServicesBaseImpl {
#Override
public String getCustomName(User user) {
// TODO Auto-generated method stub
if(user == null){
return null;
}else{
return new StringBuffer().append(user.getFirstName()).append(" ").append(user.getLastName()).toString();
}
}
}
Here is the code of controller class of my another portlet, where i am making use of this service.
HelloCustomName.java
package com.test;
import java.io.IOException;
import javax.portlet.PortletException;
import javax.portlet.RenderRequest;
import javax.portlet.RenderResponse;
import com.demo.custom.services.CustomServicesUtil;
import com.liferay.portal.kernel.util.WebKeys;
import com.liferay.portal.model.User;
import com.liferay.portal.theme.ThemeDisplay;
import com.liferay.util.bridges.mvc.MVCPortlet;
public class HelloCustomName extends MVCPortlet {
#Override
public void doView(RenderRequest renderRequest,
RenderResponse renderResponse) throws IOException, PortletException {
System.out.println("--doview----");
ThemeDisplay themeDisplay = (ThemeDisplay)renderRequest.getAttribute(WebKeys.THEME_DISPLAY);
User user = themeDisplay.getUser();
String customName = CustomServicesUtil.getCustomName(user); //getting error here
System.out.println("customName:" + customName);
}
}
Please point me on how to implement resuable services? Any guidance will be really useful.
Thanks.
My mind, you don't need the complexity of services. Simply make utility classes and put this in to tomcat/lib/ext. Be sure that tomcat/lib/ext is correct configured in tomcat/conf/catalina.properties, something like this:
common.loader=${catalina.home}/lib/ext/*.jar