I am attempting a java application that has two beans it gets through Spring, one retrieved by name and one autowired. Here is that code:
package firstspring;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class FirstSpring
{
private final static Logger logger = LoggerFactory.getLogger(FirstSpring.class);
#Autowired
private Car currentCar;
public void setCurrentCar(Car car) { this.currentCar = car; }
public Car getCurrentCar() { return currentCar; }
private static void say(String message) { System.out.println(message); }
public static void main(String[] args)
{
FirstSpring firstSpring = new FirstSpring();
firstSpring.go();
}
public void go()
{
logger.info("here we go");
ApplicationContext appContext = new ClassPathXmlApplicationContext("/appContext.xml");
Car firstCar = (Car)appContext.getBean("firstCar");
say ("firstCar was " + firstCar.getColor());
say ("currentCar is " + currentCar.getColor());
}
}
and its configuration:
<?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: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-2.5.xsd">
<context:annotation-config/>
<bean id="firstCar" class="firstspring.Car">
<property name="color" value="blue" />
<property name="doors" value="2" />
<property name="transmission" value="automatic" />
</bean>
<bean id="currentCar" class="firstspring.Car" >
<property name="color" value="red" />
<property name="doors" value="4" />
<property name="transmission" value="5-speed" />
</bean>
<bean id="firstSpring" class="firstspring.FirstSpring">
<property name="currentCar" ref="currentCar" />
</bean>
</beans>
And the Car class just to make it complete:
package firstspring;
public class Car
{
String color;
int doors;
String transmission;
public String getColor() { return color; }
public void setColor(String color) { this.color = color; }
public int getDoors() { return doors; }
public void setDoors(int doors) { this.doors = doors; }
public String getTransmission() { return transmission; }
public void setTransmission(String transmission) { this.transmission = transmission; }
}
I get a null pointer exception:
INFO: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory#5e6458a6: defining beans [org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,firstCar,currentCar,firstSpring,org.springframework.context.annotation.ConfigurationClassPostProcessor.importAwareProcessor]; root of factory hierarchy
Exception in thread "main" java.lang.NullPointerException
at firstspring.FirstSpring.go(FirstSpring.java:33)
at firstspring.FirstSpring.main(FirstSpring.java:23)
firstCar was blue
I've tried various other things -- putting 'byName' on the currentCar bean in the configuration, but I don't think that's necessary according to what documentation I've read. What am I missing here?
When you say new FirstSpring(), you're creating your own instance of that class which is outside of Spring's control, so Spring can't autowire it. Therefore when you get to currentCar.getColor(), currentCar is null. For this to work properly, you'd need to create your ApplicationContext in the main method, get the FirstSpring instance from Spring, and invoke go() on that instead of creating the object yourself.
In short, Spring cannot and will not manage (that is, autowire, initialize, destroy, etc.) any object that it didn't create itself.*
*Unless you're using AspectJ with bytecode weaving to accomplish this, but that's a rather advanced topic that you probably don't want to touch yet, unless you have other experience with AspectJ.
Related
I am learning Spring and was trying to implement the following code from the book "Spring in Action". I am not able to understand as to why the Interface property declared with exact name works and else doesn't for a simple Spring application(3.0). Please look into this:
public interface Instrument {
public void play();
}
public interface Performer
{
void perform();
}
public class Saxophone implements Instrument
{
public void play() {
System.out.println("TOOT TOOT TOOT");
}
}
public class Instrumentalist implements Performer
{
private String song;
private Instrument obj; *// not working
// private Instrument instrument; This will work, if replaced* accordingly in the code
public void setSong(String song)
{
this.song=song;
}
public void setInstrument(Instrument instrumen)
{
obj=instrumen;
}
public Instrument getInstrument()
{
return obj;
}
public String getSong()
{
return song;
}
public void perform(){
System.out.println("Playing "+song+" : ");
obj.play();
}
}
The Main class is :
import org.springframework.context.*;
import org.springframework.context.support.*;
class Main
{
public static void main(String ar[])
{
ApplicationContext ctx = new ClassPathXmlApplicationContext("abc.xml");
Performer performer = (Performer) ctx.getBean("kenny");
performer.perform();
}
}
And the configuration are:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"
default-init-method="turnONLights" default-destroy-method="turnOFFLights">
<bean id="kenny" class="Instrumentalist">
<property name="song" value="Jingle Bells" />
<property name="obj" ref="saxophone" />
<!-- here also I need to replace obj with "instrument" to make it work -->
</bean>
<bean id="saxophone" class="Saxophone"/>
</beans>
This might be a basic question but yet I am not able to get it.Please help me understand that is it necessary to have the Interface variable have the same name?
Many Thanks
This part looks incorrect...
<property name="obj" ref="saxophone" />
The value of the name attribute needs to be derived from the setter method; in this case, it looks like you want...
<property name="instrument" ref="saxophone" />
Notice that the characters s-e-t are removed, and the first character -- 'i' -- is lower case.
Trying to autowire Spring bean with property, but still getting NPE. Snippets:
INFO: Loading XML bean definitions from class path resource [autoWireByName.xml]
Exception in thread "main" today do push-ups for 30 mins
java.lang.NullPointerException
at com.springAutoWireByName.KabadiCoach.getFortune(KabadiCoach.java:23)
at com.springAutoWireByName.AutoWireByName.main(AutoWireByName.java:13)
KabadiCoach.java
package com.springAutoWireByName;
public class KabadiCoach {
private SadFortune sadFortune;
/*public KabadiCoach(){
System.out.println("inside default Constructor");
}*/
public String getDailyWorkout()
{
return "today do push-ups for 30 mins";
}
public void setSadFortune(SadFortune fortune) {
sadFortune = fortune;
}
public String getFortune() {
return sadFortune.getSadFortune();
}
}
SadFortune.java
package com.springAutoWireByName;
public class SadFortune {
public String getSadFortune()
{
System.out.println();
return "your day wont be good enough Sorry!!!";
}
}
<?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: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">
<!-- bean definitions here -->
<bean name="Fortune" class="com.springAutoWireByName.SadFortune">
</bean>
<bean id="myCoach" class="com.springAutoWireByName.KabadiCoach" autowire="byName" />
<!-- this is just a prototype to define actual just make use of this file-->
</beans>
main
package com.springAutoWireByName;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class AutoWireByName {
public static void main(String[] args) {
ClassPathXmlApplicationContext context =new ClassPathXmlApplicationContext("autoWireByName.xml");
KabadiCoach co = context.getBean("myCoach",KabadiCoach.class);
System.out.println(co.getDailyWorkout());
System.out.println(co.getFortune());
}
}
after running the above code I am getting the error message as listed and when I change the method to static
public static String getSadFortune()
{
System.out.println();
return "your day wont be good enough Sorry!!!";
}
In class 2 I got the desired output. Why?
Basically the SadFortune member is still null, which is why it works if the getSadFortune() method will be made static.
Until now you only tell Spring to instantiate a Fortune bean and a KabadiCoach, but you have to tell Spring that some members in the KabadiCoach need to be autowired too.
Try this in your Spring configuration file:
<bean id="fortune" class="com.springAutoWireByName.SadFortune"></bean>
<bean id="myCoach" class="com.springAutoWireByName.KabadiCoach" autowire="byName">
<property name="fortune" ref="fortune" />
</bean>
EDIT: Sorry, overread the autowire="byName" attribute. In this case you probably just have write the name in lower case.
<bean id="fortune" class="com.springAutoWireByName.SadFortune"/>
<bean id="myCoach" class="com.springAutoWireByName.KabadiCoach" autowire="byName"/>
ABSTRACT:
I have some initialisation operations executed in #PostConstruct of #Service ServiceInitialiserFacsimile. Those operations include a call to a method after whose execution an Aspect (DoAttionalStuffAspect) is applied.
The Aspect is instantied through aspectOf, so it is handled by the Spring Container, but unfortunately its dependencies are injected AFTER the execution of ServiceInitialiserFacsimile #PostConstruct, resulting in a NullPointerException.
How can I tell the Spring Container to inject first the fields in the Aspect and then instantiate the ServiceInitialiserFacsimile ?
I tried with an Autowired constructor for the aspect, but I think in the end AspectJ requires the no-arg constructor, so it was no help
CODE
This is a Sample I created in order to reproduce the issue I have in a much more complicated app. Here is the project if you want to check it out. https://github.com/alessiop86/spring3-mvc-maven-xml-hello-world
Code below:
This is the initialisation class:
#Component
public class ServiceInitialiserFacsimile {
private final SampleService sampleService;
#Autowired
public ServiceInitialiserFacsimile(SampleService ss) {
this.sampleService = ss;
}
#PostConstruct
public void initialiseAllTheServices() {
this.sampleService.init();
}
}
This is the service with some custom logic that requires to be initialised by the ServiceInitialiserFacsimile #PostConstruct:
#Service
public class SampleService {
public void init() {
System.out.println("do some stuff");
try {
execute();
}
catch(Exception e) {
System.err.println("I do not want to block to whole framework initialisation");
}
}
#DoAdditionalStuff
public void execute() {
System.out.println("Phase 1");
}
}
This is the annotation I use in the aspect definition
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.METHOD)
public #interface DoAdditionalStuff {
}
This is the aspect
#Aspect
public class AdditionalStuffAspect {
private AdditionalStuffService service;
public AdditionalStuffService getService() {
return service;
}
public void setService(AdditionalStuffService service) {
this.service = service;
}
#Pointcut(value="execution(public * *(..))")
private void anyPublicMethod() { }
#AfterReturning("anyPublicMethod() && #annotation(doAdditionalStuff)")
public void afterReturning(JoinPoint jointPoint, DoAdditionalStuff doAdditionalStuff) {
System.out.println(jointPoint);
service.doStuff();
}
}
This is the service that is created, but not yet instantiated when the aspect is run:
#Service
public class AdditionalStuffService {
public void doStuff() {
System.out.println("Phase2: additional stuff");
}
}
Spring context xml configuration file:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd">
<context:component-scan base-package="initialisation.mess"/>
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix">
<value>/WEB-INF/views/jsp/</value>
</property>
<property name="suffix">
<value>.jsp</value>
</property>
</bean>
<mvc:resources mapping="/resources/**" location="/resources/"/>
<mvc:annotation-driven/>
<bean class="initialisation.mess.aspects.AdditionalStuffAspect" factory-method="aspectOf">
<property name="service" ref="additionalStuffService" />
</bean>
</beans>
I was able to enforce a dependency on the ServiceInitialiserFacsimile from the Aspect by setting an id in the xml:
<bean id="myAspect" class="initialisation.mess.aspects.AdditionalStuffAspect" factory-method="aspectOf">
<property name="service" ref="additionalStuffService" />
</bean>
and then specifying the dependency of ServiceInitialiserFacsimile from the spring managed AdditionalStuffAspect with a #DependsOn annotation:
#Component
#DependsOn("myAspect")
public class ServiceInitialiserFacsimile {
private final SampleService sampleService;
#Autowired
public ServiceInitialiserFacsimile(SampleService ss) {
this.sampleService = ss;
}
#PostConstruct
public void initialiseAllTheServices() {
this.sampleService.init();
}
}
#required annotation usage. I tried giving this above setter method and tried to find the bean from context without setting this dependency. I got the object with the dependency is set null, my expectation was spring will throw some exception. Please guide me where I am doing wrong?
#Required to make it mandatory that the dependency has to be injected
Let us example:
We need to use RequiredAnnotationPostProcessor which checks whether #Required dependencies have been injected or not
public class BankService {
private CustomerService customerService;
private BillPaymentService billPaymentService;
#Required
public void setCustomerService(CustomerService customerService) {
this.customerService = customerService;
}
#Required
public void setBillPaymentService(BillPaymentService billPaymentService) {
this.billPaymentService = billPaymentService;
}
}
The configuration is like
<bean id="custService" class="xml.CustomerServiceImpl" />
<bean id="billingService" class="xml.BillPaymentServiceImpl" />
<bean id="bankService" class="xml.BankServiceImpl">
<property name="customerService" ref="custService" />
<property name="billPaymentService" ref="billingService" />
</bean>
<bean class=”o.s.beans.factory.annotation.RequiredAnnotationBeanPostProcessor" />
If we don’t set both the properties we will get an error for the BankService configuration as both are #Required.
I hope this helps!!
Same anwer by bmt - just adding here what i did to verify.
package com.requiredAnnotation;
import org.springframework.beans.factory.annotation.Required;
public class BankService {
private CustomerService customerService;
private BillPaymentService billPaymentService;
#Required
public void setCustomerService(CustomerService customerService) {
this.customerService = customerService;
}
#Required
public void setBillPaymentService(BillPaymentService billPaymentService) {
this.billPaymentService = billPaymentService;
}
public BillPaymentService getBillPaymentService() {
return billPaymentService;
}
public CustomerService getCustomerService() {
return customerService;
}
}
package com.requiredAnnotation;
public class CustomerService {
}
package com.requiredAnnotation;
public class BillPaymentService {
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<bean id="customerService" class="com.requiredAnnotation.CustomerService" />
<bean id="billPaymentService" class="com.requiredAnnotation.BillPaymentService" />
<bean id="bankService" class="com.requiredAnnotation.BankService">
<property name="customerService" ref="customerService" />
<!-- <property name="billPaymentService" ref="billPaymentService" /> -->
</bean>
<bean class="org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor" />
</beans>
package com.requiredAnnotation;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test {
public static void main(String[] args) {
ConfigurableApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:com/requiredAnnotation/beans-required.xml");
BankService bankService = applicationContext.getBean(BankService.class);
System.out.println("bankService got.");
System.out.println("getCustomerService - " + bankService.getCustomerService());
System.out.println("getBillPaymentService - " + bankService.getBillPaymentService());
}
}
Pardon me if it is a stupid question.I'm trying to learn Spring MVC,Hibernate,Junit by doing a project. I'm using MySQL database. Problem is I'm not understanding how to test DAO layer or Service layer of my project Junit.I've tested my model classes easily. I searched for DAO & Service layers, but the tutorials I saw,made me more confused. None of them actually match pattern of my project. I know in-memory used for testing process. Some testing configuration is also needed. Somewhere text-context,somewhere used java configuration class. Now, I actually want to know what steps I really have to do one by one to test this layers and it will be helpful if you can tell me what have to be done in each step. I've several DAO,Service,and Model classes. I've given one class from each layer.
My servlet-context.xml file which is in WEB-INF:
<?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:mvc="http://www.springframework.org/schema/mvc" xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">
<!-- Enable #Controller annotation support -->
<mvc:annotation-driven />
<!-- Map simple view name such as "test" into /WEB-INF/test.jsp -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/" />
<property name="suffix" value=".jsp" />
</bean>
<!-- Scan classpath for annotations (eg: #Service, #Repository etc) -->
<context:component-scan base-package="com.mahin"/>
<!-- JDBC Data Source. It is assumed you have MySQL running on localhost port 3306 with
username root and blank password. Change below if it's not the case -->
<bean id="myDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/webchatapp"/>
<property name="username" value="root"/>
<property name="password" value=""/>
<property name="validationQuery" value="SELECT 1"/>
</bean>
<!-- Hibernate Session Factory -->
<bean id="mySessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="myDataSource"/>
<property name="packagesToScan">
<array>
<value>com.mahin.models</value>
</array>
</property>
<property name="hibernateProperties">
<value>
hibernate.dialect=org.hibernate.dialect.MySQLDialect
</value>
</property>
</bean>
<!-- Hibernate Transaction Manager -->
<bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="mySessionFactory"/>
</bean>
<!-- Activates annotation based transaction management -->
<tx:annotation-driven transaction-manager="transactionManager"/>
</beans>
One of my model class
package com.mahin.models;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
#Entity
#Table(name="friends")
public class Friends {
#Id #GeneratedValue
private long friendid;
private long reqsender;
private long reqreceiver;
private int rank;
private boolean granted;
public long getFriendid() {
return friendid;
}
public void setFriendid(long friendid) {
this.friendid = friendid;
}
public long getReqsender() {
return reqsender;
}
public void setReqsender(long reqsender) {
this.reqsender = reqsender;
}
public long getReqreceiver() {
return reqreceiver;
}
public void setReqreceiver(long reqreceiver) {
this.reqreceiver = reqreceiver;
}
public int getRank() {
return rank;
}
public void setRank(int rank) {
this.rank = rank;
}
public boolean getGranted() {
return granted;
}
public void setGranted(boolean granted) {
this.granted = granted;
}
}
One of my DAO class
package com.mahin.daos;
import java.util.List;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import com.mahin.models.Friends;
#Repository
public class FriendsDAOimpl implements FriendsDAO{
#Autowired
private SessionFactory sessionFactory;
private Session getCurrentSession() {
return sessionFactory.getCurrentSession();
}
#Override
public void addFriend(Friends friend) {
getCurrentSession().save(friend);
}
#Override
public void updateFriend(Friends friend) {
Friends friendToUpdate = getFriend(friend.getFriendid());
friendToUpdate.setGranted(friend.getGranted());
friendToUpdate.setRank(friend.getRank());
friendToUpdate.setReqreceiver(friend.getReqreceiver());
friendToUpdate.setReqsender(friend.getReqsender());
getCurrentSession().update(friendToUpdate);
}
#Override
public Friends getFriend(long friendid) {
Friends friend = (Friends) getCurrentSession().get(Friends.class, friendid);
return friend;
}
#Override
public void deleteFriend(long friendid) {
Friends friend = getFriend(friendid);
if (friend != null)
getCurrentSession().delete(friend);
}
#SuppressWarnings("unchecked")
#Override
public List<Friends> getFriends() {
return getCurrentSession().createQuery("from friends").list();
}
}
And finally one of my Service class
package com.mahin.services;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.mahin.daos.FriendsDAO;
import com.mahin.models.Friends;
#Service
#Transactional
public class FriendsServiceimpl implements FriendsService{
#Autowired
private FriendsDAO friendsDAO;
#Override
public void addFriend(Friends friend) {
friendsDAO.addFriend(friend);
}
#Override
public void updateFriend(Friends friend) {
friendsDAO.updateFriend(friend);
}
#Override
public Friends getFriend(long friendid) {
return friendsDAO.getFriend(friendid);
}
#Override
public void deleteFriend(long friendid) {
friendsDAO.deleteFriend(friendid);
}
#Override
public List<Friends> getFriends() {
return friendsDAO.getFriends();
}
}
You have two options:
Unit Testing: Test if the method works as expected in isolation. This is the solely purpose of JUnit. For unit testing, you must not connect to external resources like a database. This is, you have to mock your data source provider and any other component that is external to the class you're testing. You can mock methods and classes using a mock framework like PowerMock, EasyMock or Mockito.
Integration Testing: Test if the method works as expected in an integrated environment. Here you test if the class can interact with other external resources like database connection, and perform its functionality integrated with these components.
For Spring projects, there is Spring Test framework which provides additional functionalities to JUnit test classes to do Unit or Integration Testing. Here's a basic example to perform integration test on your posted Dao class:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration("path/to/your/spring-config.xml")
public class MyTest {
#Autowired
FriendsDAO friendsDao;
#Test
public void testAddFriend() {
final int rank = 1;
Friends friend = new Friends();
friend.setRank(rank);
friendsDao.addFriend(friend);
final long friendId = friend.getId();
Friends insertedFriend = friendsDao.getFriend(friendId);
Assert.assertEquals(insertedFriend.getRank(), friend.getRank());
//assert if all necessary fields are equal
//or assert if both are equals in case your Friends class implements equals method
}
}